diff --git a/modules/radio.py b/modules/radio.py index 6bc12c4..f985286 100644 --- a/modules/radio.py +++ b/modules/radio.py @@ -436,14 +436,30 @@ def decode_wsjtx_packet(data): return None def check_callsign_match(message, callsigns): - """Check if any watched callsign appears in the message""" + """Check if any watched callsign appears in the message + + Uses word boundary matching to avoid false positives like matching + 'K7' when looking for 'K7MHI'. Callsigns are expected to be + separated by spaces or be at the start/end of the message. + """ if not callsigns: return True # If no filter, accept all message_upper = message.upper() + # Split message into words for exact matching + words = message_upper.split() + for callsign in callsigns: - if callsign in message_upper: + callsign_upper = callsign.upper() + # Check if callsign appears as a complete word + if callsign_upper in words: return True + # Also check for callsigns in compound forms like "K7MHI/P" or "K7MHI-7" + for word in words: + if word.startswith(callsign_upper + '/') or word.startswith(callsign_upper + '-'): + return True + if word.endswith('/' + callsign_upper) or word.endswith('-' + callsign_upper): + return True return False async def wsjtxMonitor(): diff --git a/modules/test_bot.py b/modules/test_bot.py index 75a1ecc..8e6f188 100644 --- a/modules/test_bot.py +++ b/modules/test_bot.py @@ -442,7 +442,13 @@ class TestBot(unittest.TestCase): self.assertTrue(check_callsign_match("CQ W1AW FN31", ["K7MHI", "W1AW"])) self.assertTrue(check_callsign_match("K7MHI DE W1AW", ["K7MHI", "W1AW"])) - print("Callsign filtering tests passed") + # Test portable/mobile suffixes + self.assertTrue(check_callsign_match("CQ K7MHI/P CN87", ["K7MHI"])) + self.assertTrue(check_callsign_match("W1AW-7", ["W1AW"])) + + # Test no false positives with partial matches + self.assertFalse(check_callsign_match("CQ K7MHIX CN87", ["K7MHI"])) + self.assertFalse(check_callsign_match("K7 TEST", ["K7MHI"]))