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

p2 Medium — planned work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants