Skip to content

fix: rate limit behaviour for multi-channel spam - #86

Merged
ghostdevv merged 8 commits into
mainfrom
fix/rate-limit
Aug 11, 2026
Merged

fix: rate limit behaviour for multi-channel spam#86
ghostdevv merged 8 commits into
mainfrom
fix/rate-limit

Conversation

@theetrain

@theetrain theetrain commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Problem

  • members rapidly posting 3+ messages within a 10-second period in a single channel were incorrectly flagged as multi-channel spam attempts because the rate limit on the messages alone would short-circuit the logic and not check for multi-channel spam.
    if (available_uses > 0 && channels.size < this.unique_channels) {
    if (consume) {
    this.available_uses.set(key, {
    limit: available_uses - 1,
    channel_ids: channels.add(channelId),
    });
    }
    return false;
    }
  • Those members were timed out as a result.
    // Timeout
    await Promise.allSettled([
    timeout(member, 43_200_000, 'Multi-channel spam'),
    mod_log(
    message.client,
    `User ${userMention(message.author.id)} was suspected of spamming and was timed out.`,
    ),
    ]);

Solution

  • adjust rate limit logic to correctly detect multi-channel usage
  • remove timeout for now, so we can opt back in via an environment variable. For now, mutli-channel-spam is logged to moderators.

Todos

  • Fix multi-channel spam rate limit detection
  • Remove timeout on multi-channel spam
  • Add unit test
  • Add config flag to timeout on multi channel spam

- Ensure rate limit uses are checked when EITHER messages haven't
  reached available uses, or the number of unique channels wasn't met
- Add tests for ratelimit class
- Add cleanup method for ratelimit class setTimeout to allow test runner
  to exit gracefully
- Update lint workflow to run tests in CI
- remove redundant `consume` param
@theetrain
theetrain requested a review from ghostdevv July 27, 2026 04:43
@theetrain
theetrain marked this pull request as ready for review July 27, 2026 04:43
Comment on lines +77 to +79
get action(): SpamActionValues {
return SPAM_FILTER_MULTI_CHANNEL_ACTION ?? 'log';
},

@theetrain theetrain Jul 27, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This entire file underwent a big refactor to be more config-based (and eventually, CMS-config-based).

One important change is here; to only log multi channel spam attempts rather than time out.

Comment thread src/utils/ratelimit.ts
channel_ids: channels.add(channelId),
});
}
if (available_uses > 0 || channels.size < this.unique_channels) {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here's the important fix, from && to || so that unique channel checks can be made without short-circuiting.

Comment thread src/utils/ratelimit.ts Outdated
this.available_uses.delete(key);
}, this.time_period);

RateLimitStore.timers.push(timer);

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will probably cause a memory leak.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@theetrain
theetrain marked this pull request as draft July 27, 2026 12:08
@theetrain
theetrain marked this pull request as ready for review July 27, 2026 14:22
@ghostdevv ghostdevv changed the title Fix rate limit behaviour for multi-channel spam fix: rate limit behaviour for multi-channel spam Aug 11, 2026
@ghostdevv
ghostdevv merged commit b7f9c65 into main Aug 11, 2026
1 check passed
@ghostdevv
ghostdevv deleted the fix/rate-limit branch August 11, 2026 18:15
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