mirror of
https://github.com/agessaman/meshcore-bot.git
synced 2026-06-03 22:31:18 +00:00
c69a3af4e6
Moves _BotAdminServer to modules/admin_server.py (renamed BotAdminServer) and the create_default_config method + 360-line template string to modules/default_config.py. core.py shrinks from 2,289 to ~1,870 lines; all 44 core tests and 2866 total tests still pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
373 lines
13 KiB
Python
373 lines
13 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Default configuration template for MeshCore Bot.
|
|
|
|
Call ``create_default_config(path)`` to write config.ini when none exists.
|
|
"""
|
|
|
|
DEFAULT_CONFIG = """[Connection]
|
|
# Connection type: serial, ble, or tcp
|
|
# serial: Connect via USB serial port
|
|
# ble: Connect via Bluetooth Low Energy
|
|
# tcp: Connect via TCP/IP
|
|
connection_type = serial
|
|
|
|
# Serial port (for serial connection)
|
|
# Common ports: /dev/ttyUSB0, /dev/tty.usbserial-*, COM3 (Windows)
|
|
serial_port = /dev/ttyUSB0
|
|
|
|
# BLE device name (for BLE connection)
|
|
# Leave commented out for auto-detection, or specify exact device name
|
|
#ble_device_name = MeshCore
|
|
|
|
# TCP hostname or IP address (for TCP connection)
|
|
#hostname = 192.168.1.60
|
|
# TCP port (for TCP connection)
|
|
#tcp_port = 5000
|
|
|
|
# Connection timeout in seconds
|
|
timeout = 30
|
|
|
|
[Bot]
|
|
# Bot name for identification and logging
|
|
bot_name = MeshCoreBot
|
|
|
|
# RF Data Correlation Settings
|
|
# Time window for correlating RF data with messages (seconds)
|
|
rf_data_timeout = 15.0
|
|
|
|
# Time to wait for RF data correlation (seconds)
|
|
message_correlation_timeout = 10.0
|
|
|
|
# Enable enhanced correlation strategies
|
|
enable_enhanced_correlation = true
|
|
|
|
# Bot node ID (leave empty for auto-assignment)
|
|
node_id =
|
|
|
|
# Enable/disable bot responses
|
|
# true: Bot will respond to keywords and commands
|
|
# false: Bot will only listen and log messages
|
|
enabled = true
|
|
|
|
# Passive mode (only listen, don't respond)
|
|
# true: Bot will not send any messages
|
|
# false: Bot will respond normally
|
|
passive_mode = false
|
|
|
|
# Rate limiting in seconds between messages
|
|
# Prevents spam by limiting how often the bot can send messages
|
|
rate_limit_seconds = 2
|
|
|
|
# Bot transmission rate limit in seconds between bot messages
|
|
# Prevents bot from overwhelming the mesh network
|
|
bot_tx_rate_limit_seconds = 1.0
|
|
|
|
# Transmission delay in milliseconds before sending messages
|
|
# Helps prevent message collisions on the mesh network
|
|
# Recommended: 100-500ms for busy networks, 0 for quiet networks
|
|
tx_delay_ms = 250
|
|
|
|
# DM retry settings for improved reliability (meshcore-2.1.6+)
|
|
# Maximum number of retry attempts for failed DM sends
|
|
dm_max_retries = 3
|
|
|
|
# Maximum flood attempts (when path reset is needed)
|
|
dm_max_flood_attempts = 2
|
|
|
|
# Number of attempts before switching to flood mode
|
|
dm_flood_after = 2
|
|
|
|
# Timezone for bot operations
|
|
# Use standard timezone names (e.g., "America/New_York", "Europe/London", "UTC")
|
|
# Leave empty to use system timezone
|
|
timezone =
|
|
|
|
# Bot location for geographic proximity calculations and astronomical data
|
|
# Default latitude for bot location (decimal degrees)
|
|
# Example: 40.7128 for New York City, 48.50 for Victoria BC
|
|
bot_latitude = 40.7128
|
|
|
|
# Default longitude for bot location (decimal degrees)
|
|
# Example: -74.0060 for New York City, -123.00 for Victoria BC
|
|
bot_longitude = -74.0060
|
|
|
|
# Interval-based advertising settings
|
|
# Send periodic flood adverts at specified intervals
|
|
# 0: Disabled (default)
|
|
# >0: Send flood advert every N hours
|
|
advert_interval_hours = 0
|
|
|
|
# Send startup advert when bot finishes initializing
|
|
# false: No startup advert (default)
|
|
# zero-hop: Send local broadcast advert
|
|
# flood: Send network-wide flood advert
|
|
startup_advert = false
|
|
|
|
# Auto-manage contact list when new contacts are discovered
|
|
# device: Device handles auto-addition using standard auto-discovery mode, bot manages contact list capacity (purge old contacts when near limits)
|
|
# bot: Bot automatically adds new companion contacts to device, bot manages contact list capacity (purge old contacts when near limits)
|
|
# false: Manual mode - no automatic actions, use !repeater commands to manage contacts (default)
|
|
auto_manage_contacts = false
|
|
|
|
[Admin_ACL]
|
|
# Admin Access Control List (ACL) for restricted commands
|
|
# Only users with public keys listed here can execute admin commands
|
|
# Format: comma-separated list of public keys (without spaces)
|
|
# Example: f5d2b56d19b24412756933e917d4632e088cdd5daeadc9002feca73bf5d2b56d,another_key_here
|
|
admin_pubkeys =
|
|
|
|
# Commands that require admin access (comma-separated)
|
|
# These commands will only work for users in the admin_pubkeys list
|
|
admin_commands = repeater
|
|
|
|
[Keywords]
|
|
# Keyword-response pairs (keyword = response format)
|
|
# Available fields: {sender}, {connection_info}, {snr}, {rssi}, {timestamp}, {path}, {path_distance}, {firstlast_distance}
|
|
# {sender}: Name/ID of message sender
|
|
# {connection_info}: Path info, SNR, and RSSI combined (e.g., "01,5f (2 hops) | SNR: 15 dB | RSSI: -120 dBm")
|
|
# {snr}: Signal-to-noise ratio in dB
|
|
# {rssi}: Received signal strength indicator in dBm
|
|
# {timestamp}: Message timestamp in HH:MM:SS format
|
|
# {path}: Message routing path (e.g., "01,5f (2 hops)")
|
|
# {hops}: Total hop count only (e.g., "2" or "0"); same value as in path/connection_info
|
|
# {hops_label}: Same as hops with "hop"/"hops" and pluralization (e.g., "1 hop", "2 hops")
|
|
# {path_distance}: Total distance between all hops in path with locations (e.g., "123.4km (3 segs, 1 no-loc)")
|
|
# {firstlast_distance}: Distance between first and last repeater in path (e.g., "45.6km" or empty if locations missing)
|
|
test = "ack [@{sender}]{phrase_part} | {connection_info} | Received at: {timestamp}"
|
|
ping = "Pong!"
|
|
pong = "Ping!"
|
|
help = "Bot Help: test, ping, help, hello, cmd, advert, t phrase, @string, wx, aqi, sun, moon, solar, hfcond, satpass | Use 'help <command>' for details"
|
|
cmd = "Available commands: test, ping, help, hello, cmd, advert, t phrase, @string, wx, aqi, sun, moon, solar, hfcond, satpass"
|
|
|
|
[Channels]
|
|
# Channels to monitor (comma-separated)
|
|
# Bot will only respond to messages on these channels
|
|
# Use exact channel names as configured on your MeshCore node
|
|
monitor_channels = general,test,emergency
|
|
|
|
# Enable DM responses
|
|
# true: Bot will respond to direct messages
|
|
# false: Bot will ignore direct messages
|
|
respond_to_dms = true
|
|
|
|
[Banned_Users]
|
|
# List of banned sender names (comma-separated). Matching is prefix (starts-with):
|
|
# "Awful Username" also matches "Awful Username 🍆". No bot responses in channels or DMs.
|
|
banned_users =
|
|
|
|
[Feed_Manager]
|
|
# Enable or disable RSS/API feed subscriptions
|
|
# true: Feed manager polls configured feeds and sends updates to channels
|
|
# false: Feed manager disabled (default)
|
|
feed_manager_enabled = false
|
|
|
|
[Scheduled_Messages]
|
|
# Scheduled message format: HHMM = channel:message
|
|
# Time format: HHMM (24-hour, no colon)
|
|
# Bot will send these messages at the specified times daily
|
|
0800 = general:Good morning! Bot is online and ready.
|
|
1200 = general:Midday status check - all systems operational.
|
|
1800 = general:Evening update - bot status: Good
|
|
|
|
[Logging]
|
|
# Log level: DEBUG, INFO, WARNING, ERROR, CRITICAL
|
|
# DEBUG: Most verbose, shows all details
|
|
# INFO: Standard logging level
|
|
# WARNING: Only warnings and errors
|
|
# ERROR: Only errors
|
|
# CRITICAL: Only critical errors
|
|
log_level = INFO
|
|
|
|
# Log file path (leave empty for console only)
|
|
# Bot will write logs to this file in addition to console
|
|
# Use absolute path for Docker compatibility (e.g., /data/logs/meshcore_bot.log)
|
|
# Relative paths will resolve relative to the config file directory
|
|
log_file = meshcore_bot.log
|
|
|
|
# Enable colored console output
|
|
# true: Use colors in console output
|
|
# false: Plain text output
|
|
colored_output = true
|
|
|
|
# MeshCore library log level (separate from bot log level)
|
|
# Controls debug output from the meshcore library itself
|
|
# Options: DEBUG, INFO, WARNING, ERROR, CRITICAL
|
|
meshcore_log_level = INFO
|
|
|
|
[Custom_Syntax]
|
|
# Custom syntax patterns for special message formats
|
|
# Format: pattern = "response_format"
|
|
# Available fields: {sender}, {phrase}, {connection_info}, {snr}, {timestamp}, {path}
|
|
# {phrase}: The text after the trigger (for t_phrase syntax)
|
|
#
|
|
# Special syntax: Messages starting with "t " or "T " followed by a phrase
|
|
# Example: "t hello world" -> "ack {sender}: hello world | {connection_info}"
|
|
t_phrase = "ack {sender}: {phrase} | {connection_info}"
|
|
|
|
|
|
[External_Data]
|
|
# Weather API key (future feature)
|
|
weather_api_key =
|
|
|
|
# Weather update interval in seconds (future feature)
|
|
weather_update_interval = 3600
|
|
|
|
# Tide API key (future feature)
|
|
tide_api_key =
|
|
|
|
# Tide update interval in seconds (future feature)
|
|
tide_update_interval = 1800
|
|
|
|
# N2YO API key for satellite pass information
|
|
# Get free key at: https://www.n2yo.com/login/
|
|
n2yo_api_key =
|
|
|
|
# AirNow API key for AQI data
|
|
# Get free key at: https://docs.airnowapi.org/
|
|
airnow_api_key =
|
|
|
|
# Repeater prefix API URL for prefix command
|
|
# Leave empty to disable prefix command functionality
|
|
# Configure your own regional API endpoint
|
|
repeater_prefix_api_url =
|
|
|
|
# Repeater prefix cache duration in hours
|
|
# How long to cache prefix data before refreshing from API
|
|
# Recommended: 1-6 hours (data doesn't change frequently)
|
|
repeater_prefix_cache_hours = 1
|
|
|
|
[Prefix_Command]
|
|
# Enable or disable repeater geolocation in prefix command
|
|
# true: Show city names with repeaters when location data is available
|
|
# false: Show only repeater names without location information
|
|
show_repeater_locations = true
|
|
|
|
# Use reverse geocoding for coordinates without city names
|
|
# true: Automatically look up city names from GPS coordinates
|
|
# false: Only show coordinates if no city name is available
|
|
use_reverse_geocoding = true
|
|
|
|
# Hide prefix source information
|
|
# true: Hide "Source: domain.com" line from prefix command output
|
|
# false: Show source information (default)
|
|
hide_source = false
|
|
|
|
# Prefix heard time window (days)
|
|
# Number of days to look back when showing prefix results (default command behavior)
|
|
# Only repeaters heard within this window will be shown by default
|
|
# Use "prefix XX all" to show all repeaters regardless of time
|
|
prefix_heard_days = 7
|
|
|
|
# Prefix free time window (days)
|
|
# Number of days to look back when determining which prefixes are "free"
|
|
# Only repeaters heard within this window will be considered as using a prefix
|
|
# Repeaters not heard in this window will be excluded from used prefixes list
|
|
prefix_free_days = 30
|
|
|
|
[Weather]
|
|
# Default state for city name disambiguation
|
|
# When users type "wx seattle", it will search for "seattle, WA, USA"
|
|
# Use 2-letter state abbreviation (e.g., WA, CA, NY, TX)
|
|
default_state = WA
|
|
|
|
# Default country for city name disambiguation (for international weather plugin)
|
|
# Use 2-letter country code (e.g., US, CA, GB, AU)
|
|
default_country = US
|
|
|
|
# Temperature unit for weather display
|
|
# Options: fahrenheit, celsius
|
|
# Default: fahrenheit
|
|
temperature_unit = fahrenheit
|
|
|
|
# Wind speed unit for weather display
|
|
# Options: mph, kmh, ms (meters per second)
|
|
# Default: mph
|
|
wind_speed_unit = mph
|
|
|
|
# Precipitation unit for weather display
|
|
# Options: inch, mm
|
|
# Default: inch
|
|
precipitation_unit = inch
|
|
|
|
[Path_Command]
|
|
# Optional prefix on path command replies: {sender}, {connection_info}, {path}, {timestamp}, {snr}, {rssi}
|
|
# reply_prefix =
|
|
# Bytes per hop before repeater name lookup (0/1 = always; 2/3 = gate to hex + tip if shorter)
|
|
# minimum_path_bytes = 0
|
|
# Geographic proximity calculation method
|
|
# simple: Use proximity to bot location (default)
|
|
# path: Use proximity to previous/next nodes in the path for more realistic routing
|
|
proximity_method = simple
|
|
|
|
# Enable path proximity fallback
|
|
# When path proximity can't be calculated (missing location data), fall back to simple proximity
|
|
# true: Fall back to bot location proximity when path data unavailable
|
|
# false: Show collision warning when path proximity unavailable
|
|
path_proximity_fallback = true
|
|
|
|
# Maximum range for geographic proximity guessing (kilometers)
|
|
# Repeaters beyond this distance will have reduced confidence or be rejected
|
|
# Set to 0 to disable range limiting
|
|
max_proximity_range = 200
|
|
|
|
# Maximum age for repeater data in path matching (days)
|
|
# Only include repeaters that have been heard within this many days
|
|
# Helps filter out stale or inactive repeaters from path decoding
|
|
# Set to 0 to disable age filtering
|
|
max_repeater_age_days = 14
|
|
|
|
# Confidence indicator symbols for path command
|
|
# High confidence (>= 0.9): Shows when path decoding is very reliable
|
|
high_confidence_symbol = 🎯
|
|
|
|
# Medium confidence (>= 0.8): Shows when path decoding is reasonably reliable
|
|
medium_confidence_symbol = 📍
|
|
|
|
# Low confidence (< 0.8): Shows when path decoding has uncertainty
|
|
low_confidence_symbol = ❓
|
|
|
|
[Solar_Config]
|
|
# URL timeout for external API calls (seconds)
|
|
url_timeout = 10
|
|
|
|
# Use Zulu/UTC time for astronomical data
|
|
# true: Use 24-hour UTC format
|
|
# false: Use 12-hour local format
|
|
use_zulu_time = false
|
|
|
|
[Joke_Command]
|
|
# Enable or disable the joke command (true/false)
|
|
enabled = true
|
|
|
|
# Enable seasonal joke defaults (October: spooky, December: Christmas)
|
|
# true: Seasonal defaults are applied (default)
|
|
# false: No seasonal defaults (always random)
|
|
seasonal_jokes = true
|
|
|
|
# Handle long jokes (over 130 characters)
|
|
# false: Fetch new jokes until we get a short one (default)
|
|
# true: Split long jokes into multiple messages
|
|
long_jokes = false
|
|
|
|
[DadJoke_Command]
|
|
# Enable or disable the dad joke command (true/false)
|
|
enabled = true
|
|
|
|
# Handle long jokes (over 130 characters)
|
|
# false: Fetch new jokes until we get a short one (default)
|
|
# true: Split long jokes into multiple messages
|
|
long_jokes = false
|
|
|
|
"""
|
|
|
|
|
|
def create_default_config(config_file: str) -> None:
|
|
"""Write DEFAULT_CONFIG to ``config_file``.
|
|
|
|
Uses print() instead of logger since this is called before logging is set up.
|
|
"""
|
|
with open(config_file, 'w') as f:
|
|
f.write(DEFAULT_CONFIG)
|
|
print(f"Created default config file: {config_file}")
|