Skip to content

Fix EQNotify tag matching: match at word start, not raw substring#266

Merged
ebm5025 merged 2 commits into
mainfrom
claude/eqnotify-castle-bot-integration-5c7l4s
Jul 24, 2026
Merged

Fix EQNotify tag matching: match at word start, not raw substring#266
ebm5025 merged 2 commits into
mainfrom
claude/eqnotify-castle-bot-integration-5c7l4s

Conversation

@ebm5025

@ebm5025 ebm5025 commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Problem

A user received an EQNotify Telegram alert that felt unrelated to anything they'd signed up for. Root cause: tag matching used raw substring containment (content.includes(tag)), and several default tags are short — notably ct and kt. ct matches inside ordinary words like "contact", "protect", "select", so a batphone with any such word would trip the ct default and fire an alert.

(The empty-tags path was never the cause — matchesTags([]) correctly returns false. New subscribers simply carry the 9 default tags.)

Fix

Tags now match only when a word in the batphone starts with the tag (left word-boundary), instead of matching anywhere as a substring.

  • ✅ Kills the mid-word false positives: ct matches "CT POP" but not "contact" / "protect".
  • ✅ Preserves the intentional abbreviation/prefix triggers the defaults rely on: doze → "Dozekar", cazic → "Cazic-Thule", dain → "Dain Frostreaver". (Whole-word-only matching would have regressed these.)
  • ⚠️ Tradeoff: a tag no longer matches mid-word, so quake no longer hits "earthquake". Add the fuller keyword if that's wanted.

Implemented with a left word-boundary regex over the lowercased content, with the tag escaped for regex safety (tags may contain punctuation like vulak`aerr).

Changes

  • matcher.ts: matchesTags now uses a (?<[a-z0-9])<tag> word-start match; added escapeRegExp + a documented tagMatchesContent helper.
  • Tests: added a word-start (prefix) boundaries block, including the reported ct-in-contact regression and the dozeDozekar abbreviation case (17 tests total, all passing).
  • Docs: /eqnotify add-tag description and README explain the word-start rule and the default tag set.

Testing

  • yarn tsc — clean.
  • yarn test:ci (eqnotify matcher suite) — 17 tests pass.

🤖 Generated with Claude Code


Generated by Claude Code

claude added 2 commits July 24, 2026 15:56
Batphone tag matching used raw substring containment, so short default tags
like `ct` and `kt` fired inside unrelated words ("ct" in "contact",
"protect"), producing alerts that looked unrelated to anything a user signed
up for.

Tags now match only when a word in the batphone *starts with* the tag. This
kills the mid-word false positives while preserving the intentional
abbreviation/prefix triggers the defaults rely on (`doze` -> "Dozekar",
`cazic` -> "Cazic-Thule", `dain` -> "Dain Frostreaver"). The one tradeoff is
that a tag no longer matches mid-word (`quake` no longer hits "earthquake");
add the fuller keyword if that's wanted.

Implemented with a left word-boundary regex over the lowercased content, with
the tag escaped for regex safety. Adds regression tests, including the
reported "ct"-in-"contact" case.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BWXRmPbtEz35wquwFd8Cu7
Complements the word-start matching change: `quake` no longer matches inside
"earthquake", so add `earthquake` as a default alongside `quake` to cover
both batphone phrasings. Applies to new registrations; existing subscribers
can add it with `/eqnotify add-tag earthquake`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BWXRmPbtEz35wquwFd8Cu7
@ebm5025
ebm5025 merged commit 0668f93 into main Jul 24, 2026
1 check passed
@ebm5025
ebm5025 deleted the claude/eqnotify-castle-bot-integration-5c7l4s branch July 24, 2026 16:00
ebm5025 added a commit that referenced this pull request Jul 24, 2026
…mit (#267)

The add-tag option description introduced in #266 was 108 characters, over
Discord's 100-character cap for option descriptions. discord.js validates
this only at command-registration time, so it passed tsc/tests but crashed
the bot on boot ("ExpectedConstraintError: Invalid string length"). Shortened
to 93 characters and noted the limit inline.


Claude-Session: https://claude.ai/code/session_01BWXRmPbtEz35wquwFd8Cu7

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants