Files
MeshCore-Solo/examples/companion_radio/MyMeshBot.h
Jakub 71635e5e6f Bot: DM+channel modes with separate replies; buzzer auto-mute; UX fixes
- Bot redesign: DM bot active for all private messages (no pubkey filter),
  channel bot optional with separate enable flag; both can run simultaneously
- Bot: one shared trigger, separate reply texts for DM and channel
- Buzzer: add Auto mode (mutes when BT connected, unmutes on disconnect);
  per-channel force-on overrides still work as intended
- Settings: defer flash writes to menu exit (only when dirty)
- Settings: add Seconds toggle (hide clock seconds, refresh drops 1s→60s)
- Fullscreen msg preview: fix truncation (fmsg buf 79→140 chars)
- RingtoneEditor: fix melody playback cut after first note (RTTTL lib holds
  pointer — moved play buffer to member variable)
- BotScreen: remove key hint footer
- .gitattributes: protect README.md from upstream merge conflicts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 21:09:47 +02:00

60 lines
2.1 KiB
C

#pragma once
// Bot logic — not part of upstream MyMesh.cpp.
// Included at the bottom of MyMesh.cpp after all class definitions.
void MyMesh::tryBotReplyDM(const ContactInfo& from, const char* text) {
if (!(_prefs.bot_enabled && _prefs.bot_trigger[0] && _prefs.bot_reply_dm[0] &&
millis() - _bot_last_reply_ms > 10000UL))
return;
const char* tr = _prefs.bot_trigger;
int tlen = strlen(tr);
bool matched = false;
for (const char* t = text; *t && !matched; t++) {
int i = 0;
while (i < tlen && tolower((uint8_t)t[i]) == tolower((uint8_t)tr[i])) i++;
if (i == tlen) matched = true;
}
if (!matched) return;
uint32_t ts = getRTCClock()->getCurrentTime();
char expanded[200];
expandMsg(_prefs.bot_reply_dm, expanded, sizeof(expanded),
sensors.node_lat, sensors.node_lon,
sensors.node_lat != 0.0 || sensors.node_lon != 0.0,
ts, _prefs.tz_offset_hours);
uint32_t expected_ack, est_timeout;
if (sendMessage(from, ts, 0, expanded, expected_ack, est_timeout) != MSG_SEND_FAILED)
_bot_last_reply_ms = millis();
}
void MyMesh::tryBotReplyChannel(uint8_t channel_idx, const char* text) {
if (!(_prefs.bot_channel_enabled && _prefs.bot_trigger[0] && _prefs.bot_reply_ch[0] &&
channel_idx == _prefs.bot_channel_idx &&
millis() - _bot_last_reply_ms > 10000UL))
return;
const char* tr = _prefs.bot_trigger;
int tlen = strlen(tr);
bool matched = false;
for (const char* t = text; *t && !matched; t++) {
int i = 0;
while (i < tlen && tolower((uint8_t)t[i]) == tolower((uint8_t)tr[i])) i++;
if (i == tlen) matched = true;
}
if (!matched) return;
ChannelDetails ch;
if (!getChannel(channel_idx, ch)) return;
uint32_t ts = getRTCClock()->getCurrentTime();
char expanded[200];
expandMsg(_prefs.bot_reply_ch, expanded, sizeof(expanded),
sensors.node_lat, sensors.node_lon,
sensors.node_lat != 0.0 || sensors.node_lon != 0.0,
ts, _prefs.tz_offset_hours);
int rlen = strlen(expanded);
if (sendGroupMessage(ts, ch.channel, _prefs.node_name, expanded, rlen))
_bot_last_reply_ms = millis();
}