Conversation
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (3)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Bugbot Autofix prepared fixes for 1 of the 1 bugs found in the latest run.
Or push these changes by commenting: |
- Add rateLimit configuration to config.json with configurable limits - Create src/utils/rateLimit.js with sliding window rate limiting logic - Integrate rate limiting into AI chat message handler - Add automatic cleanup of old rate limit entries - Provide user-friendly rate limit exceeded messages Closes review comment about dev config files (not included in this commit)
8e5f095 to
19dc04f
Compare
|
Closing - conflicts with modular architecture refactor |
…s in memory command - Use splitMessage() utility instead of manual substring truncation for Discord's 2000-char limit, properly handling multi-byte characters (#1) - Include memory IDs in searchMemories results and use them directly in handleForgetTopic instead of fragile text equality matching (#2) - Parallelize deleteMemory calls with Promise.allSettled instead of sequential for loop (#3) - Verify deferReply is called in all forget test variants (#7)
…s in memory command - Use splitMessage() utility instead of manual substring truncation for Discord's 2000-char limit, properly handling multi-byte characters (#1) - Include memory IDs in searchMemories results and use them directly in handleForgetTopic instead of fragile text equality matching (#2) - Parallelize deleteMemory calls with Promise.allSettled instead of sequential for loop (#3) - Verify deferReply is called in all forget test variants (#7)
…s in memory command - Use splitMessage() utility instead of manual substring truncation for Discord's 2000-char limit, properly handling multi-byte characters (#1) - Include memory IDs in searchMemories results and use them directly in handleForgetTopic instead of fragile text equality matching (#2) - Parallelize deleteMemory calls with Promise.allSettled instead of sequential for loop (#3) - Verify deferReply is called in all forget test variants (#7)
…uard - Add cursor-based pagination with `after` param to fetchUserGuilds, looping until all guilds are fetched (issue #2) - Propagate RefreshTokenError to session and auto-redirect to sign-in via SessionGuard component in Providers (issue #3) - Add dockerContext = ".." to railway.toml for monorepo Docker builds (issue #4) - Create /api/health returning 200 JSON; update railway.toml healthcheckPath (issue #5) - Conditionally render Add to Server buttons only when CLIENT_ID is set (issue #6) - Add AbortController cleanup to guild fetch useEffect in ServerSelector (issue #7) - Refuse unauthenticated bot API requests when BOT_API_SECRET is missing (issue #9) - Add retry + empty/error states to ServerSelector (issue #13 partial)
- Differentiate requireGuildAdmin (ADMINISTRATOR only) from requireGuildModerator (ADMINISTRATOR | MANAGE_GUILD), aligning REST admin check with slash-command isAdmin (#1, #2, #12) - Add botOwners startup warning when using default upstream ID (#3) - Add SESSION_SECRET, DISCORD_CLIENT_SECRET, DISCORD_REDIRECT_URI to README deployment table (#4) - Pass actual permission level to getPermissionError so modlog denial says 'moderator' not 'administrator' (#5) - Guard _seedOAuthState with NODE_ENV production check (#6) - Add test: valid JWT with no server-side session (#7) - Add DiscordApiError class with HTTP status (#8) - Add moderatorRoleId support to isModerator (#9) - Remove no-op delete override from SessionStore (#10) - Cap oauthStates at 10k entries (#11) - Fix hasOAuthGuildPermission docstring for bitwise OR semantics (#12) - Handle dashboard URL fragment collision (#13) - Cap guildCache at 10k entries (#14) - Add SESSION_TTL_MS co-location comment with JWT expiry (#15) - Cache SESSION_SECRET via lazy getter in verifyJwt (#16) - Remove PII (username) from OAuth auth log (#17)
- Differentiate requireGuildAdmin (ADMINISTRATOR only) from requireGuildModerator (ADMINISTRATOR | MANAGE_GUILD), aligning REST admin check with slash-command isAdmin (#1, #2, #12) - Add botOwners startup warning when using default upstream ID (#3) - Add SESSION_SECRET, DISCORD_CLIENT_SECRET, DISCORD_REDIRECT_URI to README deployment table (#4) - Pass actual permission level to getPermissionError so modlog denial says 'moderator' not 'administrator' (#5) - Guard _seedOAuthState with NODE_ENV production check (#6) - Add test: valid JWT with no server-side session (#7) - Add DiscordApiError class with HTTP status (#8) - Add moderatorRoleId support to isModerator (#9) - Remove no-op delete override from SessionStore (#10) - Cap oauthStates at 10k entries (#11) - Fix hasOAuthGuildPermission docstring for bitwise OR semantics (#12) - Handle dashboard URL fragment collision (#13) - Cap guildCache at 10k entries (#14) - Add SESSION_TTL_MS co-location comment with JWT expiry (#15) - Cache SESSION_SECRET via lazy getter in verifyJwt (#16) - Remove PII (username) from OAuth auth log (#17)
…ks for new anchor check - Add test for backslash (\) escaping in ILIKE search (#7) - Update 'flag a message' mock to include anchorCheck query result
* feat(conversations): add flagged_messages migration * feat(conversations): add API endpoints for list, detail, search, flag, stats * feat(conversations): mount router in API index * feat(conversations): add conversation list and replay dashboard pages * feat(conversations): add Next.js API proxy routes * test(conversations): add API and grouping tests * fix(conversations): escape ILIKE wildcards to prevent wildcard injection * fix(conversations): remove unused _totalChars variable * fix(conversations): cap list query to 5000 rows to prevent memory exhaustion * fix(conversations): replace in-memory stats grouping with SQL aggregates * fix(conversations): bound conversation detail query by time window instead of full channel scan * style: alphabetize imports and format authorizeGuildAdmin calls * test(conversations): fix stats mock to match SQL conversation counting * test(conversations): add POST flag endpoint to guild validation test The auth test already covered all 5 endpoints including POST .../flag, but the guild-validation test only checked 4 GET endpoints, leaving the flag endpoint's guild validation untested. Resolves review thread PRRT_kwDORICdSM5xTeiw * fix(conversations): parameterize SQL interval and fix flag button a11y Thread 3: Replace string interpolation of CONVERSATION_GAP_MINUTES in the window-function SQL with a $2 parameter to avoid hardcoded literals. Passes CONVERSATION_GAP_MINUTES as a query value instead. Thread 4: Change flag button wrapper from `focus-within:opacity-100` to `group-focus-within:opacity-100` so the button becomes visible whenever any element in the message bubble group receives keyboard focus, not just when the button's own children are focused — matching the group-hover pattern and ensuring proper keyboard accessibility. Also: biome --write reformatted label.tsx and textarea.tsx (pre-existing style issues). * test: add ILIKE wildcard escape coverage for % and _ characters Adds test cases verifying that % and _ characters in conversation search queries are properly escaped before being used in ILIKE patterns, preventing them from acting as SQL wildcards. * fix: deterministic flag status for duplicate flagged_messages rows When a message has been flagged multiple times (flagged_messages has no UNIQUE constraint on message_id), the previous Map construction would silently overwrite entries in iteration order, making the displayed status non-deterministic. Order the SELECT by created_at DESC so the first row per message_id that lands in the Map is always the most recently created flag, giving a predictable 'latest wins' behaviour. * refactor: extract escapeIlike utility from logQuery inline impl Creates src/utils/escapeIlike.js as a shared, exported utility. Conversations route now imports it instead of duplicating the regex. * fix(conversations): use escapeIlike(), fix non-deterministic flag status, add 30-day default window, verify conversationId on flag POST - Import escapeIlike() instead of inline regex (DRY #4) - Default to last 30 days when no `from` filter to prevent unbounded LIMIT 5000 scan (#3) - Fix Map construction: iterate ORDER BY DESC rows and only set first occurrence per key so most-recent flag status wins (#1) - Verify flagged messageId belongs to the conversation's channel before inserting (#2) * test(conversations): add ILIKE backslash escape test and fix flag mocks for new anchor check - Add test for backslash (\) escaping in ILIKE search (#7) - Update 'flag a message' mock to include anchorCheck query result * refactor(web): add LOG_PREFIX constant to all 5 conversation proxy routes (#6) Each route previously inlined its prefix string on every call. Extracts to module-scope const matching the pattern used by config/members/roles routes. * fix(ui): use MessagesSquare icon for Conversations sidebar entry (#8) AI Chat already uses MessageSquare. Conversations now uses MessagesSquare to distinguish the two nav items visually. * fix(ui): show last 4 digits of channel snowflake instead of raw ID (#9) Raw Discord snowflakes are 18+ digit numbers. Showing `${channelId.slice(-4)}` gives a minimal but less jarring display until a proper channel name resolver is wired up. * refactor(ui): extract PAGE_SIZE constant in conversations page (#5) Replaces two hardcoded 25s with a single PAGE_SIZE = 25 constant. * docs(migration): explain missing FK on conversation_first_id (#10) conversation_first_id has no FK because conversations are not a separate table with their own PK. They are virtual groups derived from message rows. message_id already carries a FK for referential integrity. * fix(lint): suppress pre-existing biome a11y errors in label component * fix(conversations): stray $ in JSX channel display, increase query limit to 10k

Implement per-user and per-channel rate limiting for AI chat requests to prevent abuse and manage API costs. Configurable limits with friendly error messages when exceeded.