diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index 6b2457d3..e42afa08 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -515,37 +515,7 @@ 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); - // DM auto-reply bot - if (_prefs.bot_enabled && _prefs.bot_target_type == 1 && - _prefs.bot_trigger[0] && _prefs.bot_reply[0] && - millis() - _bot_last_reply_ms > 10000UL) { - // all-zero pubkey = any sender; otherwise match first 4 bytes - bool key_ok = (_prefs.bot_dm_pubkey[0] == 0 && _prefs.bot_dm_pubkey[1] == 0 && - _prefs.bot_dm_pubkey[2] == 0 && _prefs.bot_dm_pubkey[3] == 0) || - memcmp(from.id.pub_key, _prefs.bot_dm_pubkey, 4) == 0; - if (key_ok) { - const char* t = text; - const char* tr = _prefs.bot_trigger; - int tlen = strlen(tr); - bool matched = false; - for (; *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) { - uint32_t ts = getRTCClock()->getCurrentTime(); - char expanded[200]; - expandMsg(_prefs.bot_reply, 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(); - } - } - } + tryBotReplyDM(from, text); } void MyMesh::onCommandDataRecv(const ContactInfo &from, mesh::Packet *pkt, uint32_t sender_timestamp, @@ -605,35 +575,7 @@ void MyMesh::onChannelMessageRecv(const mesh::GroupChannel &channel, mesh::Packe if (_ui) _ui->newMsg(path_len, channel_name, text, offline_queue_len, 0); #endif - // auto-reply bot - if (_prefs.bot_enabled && _prefs.bot_trigger[0] && _prefs.bot_reply[0] && - channel_idx == _prefs.bot_channel_idx && - millis() - _bot_last_reply_ms > 10000UL) { - // case-insensitive substring match - const char* t = text; - const char* tr = _prefs.bot_trigger; - int tlen = strlen(tr); - bool matched = false; - for (; *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) { - ChannelDetails ch; - if (getChannel(channel_idx, ch)) { - uint32_t ts = getRTCClock()->getCurrentTime(); - char expanded[200]; - expandMsg(_prefs.bot_reply, 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(); - } - } - } + tryBotReplyChannel(channel_idx, text); } void MyMesh::onChannelDataRecv(const mesh::GroupChannel &channel, mesh::Packet *pkt, uint16_t data_type, @@ -2266,3 +2208,5 @@ bool MyMesh::advert() { return false; } } + +#include "MyMeshBot.h" diff --git a/examples/companion_radio/MyMesh.h b/examples/companion_radio/MyMesh.h index c9eee993..61210e6c 100644 --- a/examples/companion_radio/MyMesh.h +++ b/examples/companion_radio/MyMesh.h @@ -179,6 +179,9 @@ public: #endif private: + void tryBotReplyDM(const ContactInfo& from, const char* text); + void tryBotReplyChannel(uint8_t channel_idx, const char* text); + void writeOKFrame(); void writeErrFrame(uint8_t err_code); void writeDisabledFrame(); diff --git a/examples/companion_radio/MyMeshBot.h b/examples/companion_radio/MyMeshBot.h new file mode 100644 index 00000000..8099e9b1 --- /dev/null +++ b/examples/companion_radio/MyMeshBot.h @@ -0,0 +1,66 @@ +#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_target_type == 1 && + _prefs.bot_trigger[0] && _prefs.bot_reply[0] && + millis() - _bot_last_reply_ms > 10000UL)) + return; + + // all-zero pubkey = any sender; otherwise match first 4 bytes + bool key_ok = (_prefs.bot_dm_pubkey[0] == 0 && _prefs.bot_dm_pubkey[1] == 0 && + _prefs.bot_dm_pubkey[2] == 0 && _prefs.bot_dm_pubkey[3] == 0) || + memcmp(from.id.pub_key, _prefs.bot_dm_pubkey, 4) == 0; + if (!key_ok) 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, 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_enabled && _prefs.bot_trigger[0] && _prefs.bot_reply[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, 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(); +}