mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-07-26 14:58:12 +00:00
feat(bot): hardening + auto-responder, query commands, quiet hours
Reply-bot overhaul on top of the trigger/reply auto-reply: Robustness - single botTriggerMatches() shared by DM/channel paths; named constants (BOT_REPLY_COOLDOWN_MS / BOT_SCRATCH) replace magic numbers. - per-contact DM throttle (8-entry ring) so a second sender isn't starved while one contact is on cooldown. - channel anti-loop: skip only when an incoming message equals our own reply (was: any reply containing the trigger word — which silently killed channel replies for the common "trigger word in reply" setup). Features - away / reply-to-all: a lone "*" trigger matches every message. - independent DM vs channel triggers (bot_trigger / bot_trigger_ch); "*" works on the channel too, bounded by cooldown + echo guard. - query commands: a DM or monitored-channel message is scanned for "!word" tokens — !ping/!batt/!loc/!time/!temp/!hops/!status/!help — merged into one combined reply. DM = per-contact throttle, ignores quiet hours; channel = broadcast, per-channel cooldown, respects quiet hours. !hops uses getPathHashCount() (0 = direct). - quiet hours (bot_quiet_start/end, local, wraps midnight) silence push replies. - reply counter shown in the BotScreen header. UI / storage - BotScreen: 9 rows, scrolling list (no more cramming), field I/O via fieldBuf()/fieldCap(). - prefs bot_commands_enabled / bot_quiet_start / bot_quiet_end / bot_trigger_ch persisted; schema 0xC0DE000A → 0xC0DE000C with clamping + migration (bot_trigger_ch seeded from bot_trigger on upgrade). - docs: tools_screen bot section rewritten; FEATURES.md refreshed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -569,7 +569,13 @@ void MyMesh::onMessageRecv(const ContactInfo &from, mesh::Packet *pkt, uint32_t
|
||||
markConnectionActive(from); // in case this is from a server, and we have a connection
|
||||
queueMessage(from, TXT_TYPE_PLAIN, pkt, sender_timestamp, NULL, 0, text);
|
||||
|
||||
tryBotReplyDM(from, text);
|
||||
// hop count of the received message. getPathHashCount() (low 6 bits of path_len)
|
||||
// is the number of repeaters traversed — the same value the mesh uses for flood
|
||||
// retransmit priority. 0 = heard directly. (Raw path_len is a size/count
|
||||
// bitfield for transport packets, so it must not be used directly.)
|
||||
uint8_t hops = pkt ? pkt->getPathHashCount() : 0;
|
||||
if (!tryBotCommand(from, text, hops)) // commands take priority; fall through to trigger reply
|
||||
tryBotReplyDM(from, text);
|
||||
}
|
||||
|
||||
void MyMesh::onCommandDataRecv(const ContactInfo &from, mesh::Packet *pkt, uint32_t sender_timestamp,
|
||||
@@ -639,7 +645,9 @@ void MyMesh::onChannelMessageRecv(const mesh::GroupChannel &channel, mesh::Packe
|
||||
if (_ui) _ui->newMsg(path_len, channel_name, text, offline_queue_len, 0);
|
||||
#endif
|
||||
|
||||
tryBotReplyChannel(channel_idx, text);
|
||||
// hop count for !hops (see onMessageRecv); not the wire path_len above.
|
||||
if (!tryBotChannelCommand(channel_idx, text, pkt->getPathHashCount())) // commands take priority
|
||||
tryBotReplyChannel(channel_idx, text);
|
||||
}
|
||||
|
||||
void MyMesh::onChannelDataRecv(const mesh::GroupChannel &channel, mesh::Packet *pkt, uint16_t data_type,
|
||||
@@ -1217,8 +1225,9 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
|
||||
_last_relay_seq = 0;
|
||||
offline_queue_len = 0;
|
||||
app_target_ver = 0;
|
||||
_bot_last_dm_reply_ms = 0;
|
||||
_bot_last_ch_reply_ms = 0;
|
||||
memset(_bot_dm_log, 0, sizeof(_bot_dm_log));
|
||||
_bot_reply_count = 0;
|
||||
_next_auto_advert_ms = 0;
|
||||
clearPendingReqs();
|
||||
next_ack_idx = 0;
|
||||
@@ -1262,6 +1271,10 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
|
||||
_prefs.bot_trigger[0] = '\0';
|
||||
_prefs.bot_reply_dm[0] = '\0';
|
||||
_prefs.bot_reply_ch[0] = '\0';
|
||||
_prefs.bot_trigger_ch[0] = '\0';
|
||||
_prefs.bot_commands_enabled = 0;
|
||||
_prefs.bot_quiet_start = 0;
|
||||
_prefs.bot_quiet_end = 0; // start==end → quiet hours disabled
|
||||
_prefs.dm_show_all = 1; // show all contacts by default
|
||||
_prefs.dm_resend_count = 2; // auto-resend on-device DMs twice by default
|
||||
memset(_prefs.dm_notif, 0, sizeof(_prefs.dm_notif));
|
||||
|
||||
Reference in New Issue
Block a user