Skip to content

fix: role-mention only matches bot's own roles (with guild_create cache)#246

Open
chengli wants to merge 1 commit intoopenabdev:mainfrom
chengli:feat/role-mention-filter
Open

fix: role-mention only matches bot's own roles (with guild_create cache)#246
chengli wants to merge 1 commit intoopenabdev:mainfrom
chengli:feat/role-mention-filter

Conversation

@chengli
Copy link
Copy Markdown

@chengli chengli commented Apr 12, 2026

Summary

  • Fix role-mention detection to only match roles assigned to the receiving bot, preventing cross-triggers in multi-bot guilds
  • Cache the bot's own role IDs from guild_create events (not ready) in a RwLock<HashSet> — zero per-message API calls
  • Early-exit when msg.mention_roles is empty (skip cache read entirely)

Closes #245

Details

Bug: msg.mention_roles.iter().any(|r| msg.content.contains(...)) triggers on any role mentioned in the message, not just the bot's own roles. In a guild with bots A (role X) and B (role Y), mentioning role Y incorrectly wakes up bot A.

Fix: replace string matching with a set intersection against the bot's cached roles:

let is_role_mentioned = if !msg.mention_roles.is_empty() {
    let cached_roles = self.bot_role_ids.read().await;
    msg.mention_roles.iter().any(|r| cached_roles.contains(&r.get()))
} else {
    false
};

Technical notes:

  1. Why guild_create instead of ready? ready.guilds contains UnavailableGuild stubs. Guild member data may not be available yet, particularly for larger guilds, causing .member() lookups to 404. guild_create fires per guild after ready with complete data.

  2. Global HashSet vs per-guild HashMap: We use a flat HashSet<u64> for the cache. Discord Role IDs are globally unique and msg.mention_roles only contains roles valid for the current guild, so a flat cache is safe and keeps lookups simple.

  3. Known limitation: If a role is added to the bot while it is running, it won't be recognized until restart. A guild_member_update handler could keep the cache hot if dynamic role assignment becomes a requested feature.

Files changed

File Change
src/discord.rs Add bot_role_ids: Arc<RwLock<HashSet<u64>>> to Handler; replace string-match with cache lookup; add guild_create handler to populate cache
src/main.rs Initialize empty bot_role_ids cache

Test plan

  • cargo check passes ✅ (verified locally)
  • Single-bot guild: role mention still triggers the bot
  • Multi-bot guild: role-mentioning bot A's role does NOT trigger bot B
  • Bot has no guild roles: role mention does not trigger the bot
  • Large guild: role cache populates correctly via guild_create
  • No role mentions in message: early-exit, no cache read

The existing role-mention check matched any role mentioned in the
message, not just roles assigned to the receiving bot. In multi-bot
guilds this caused cross-triggering: mentioning bot B's role would
also wake up bot A.

Replace string matching against msg.content with a set intersection
against the bot's own cached role IDs. The cache is populated from
guild_create events (not ready, which only has UnavailableGuild stubs
for larger guilds) and stored in a RwLock<HashSet<u64>>. Early-exit
when msg.mention_roles is empty to skip the cache read entirely.

Closes openabdev#245
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.

fix: role mentions trigger unintended bots in multi-bot guilds

1 participant