Skip to content

feat: starboard — showcase popular messages (#48)#99

Merged
BillChirico merged 11 commits intomainfrom
feat/starboard
Feb 26, 2026
Merged

feat: starboard — showcase popular messages (#48)#99
BillChirico merged 11 commits intomainfrom
feat/starboard

Conversation

@BillChirico
Copy link
Collaborator

Starboard Feature

When a message gets enough star reactions (configurable threshold), it gets reposted to a dedicated starboard channel with a gold embed.

What's included

  • Migration (002_starboard-posts.cjs): starboard_posts table for dedup tracking
  • Module (src/modules/starboard.js): Full starboard logic
    • handleReactionAdd / handleReactionRemove — post, update, or remove starboard embeds
    • buildStarboardEmbed — gold (#FFD700) embed with author avatar, source channel, star count, jump link
    • getStarCount — counts reactions with self-star exclusion
    • DB helpers: findStarboardPost, insertStarboardPost, updateStarboardPostCount, deleteStarboardPost
  • Events wiring (src/modules/events.js): MessageReactionAdd / MessageReactionRemove listeners with config gate
  • Config (config.json): starboard section with defaults

Config

{
  "starboard": {
    "enabled": false,
    "channelId": null,
    "threshold": 3,
    "emoji": "",
    "selfStarAllowed": false,
    "ignoredChannels": []
  }
}

Behavior

  • Star count reaches threshold → post gold embed to starboard channel
  • More stars → update existing embed with new count
  • Stars removed below threshold → delete from starboard
  • Self-star prevention (configurable)
  • Handles attachments/images from original message
  • Handles partial reactions and messages

Tests

  • 29 starboard module tests + 6 events wiring tests (35 new tests)
  • All 1573 tests pass, lint clean

Closes #48

@claude
Copy link

claude bot commented Feb 26, 2026

Claude finished @BillChirico's task in 2m 58s —— View job


Review: PR #99 — feat: starboard

  • Read project conventions (AGENTS.md, CLAUDE.md)
  • Review all changed files
  • Post inline comments for issues found
  • Post summary and verdict

Result: 1 issue found (documentation only)

🟡 Warning: Missing AGENTS.md and README.md documentation — Per AGENTS.md §Documentation, new modules must update:

  1. AGENTS.md Key Files table — add src/modules/starboard.js
  2. AGENTS.md Database Tables — add starboard_posts
  3. AGENTS.md Common Pitfall Graceful Shutdown Handling #3 — add GuildMessageReactions intent
  4. README.md Configuration reference — add Starboard config section

All previously flagged code issues (intent, partials, dead variables, safeSend, test assertions, warn logs, redundant index, feedback loop guard) have been resolved. CI is green. The implementation is solid — just needs the docs update to comply with project conventions.

See inline comment and review verdict for details + copy-paste AI fix prompt.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 26, 2026

Warning

Rate limit exceeded

@BillChirico has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 0 minutes and 46 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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.

📥 Commits

Reviewing files that changed from the base of the PR and between e90af4e and 980114f.

📒 Files selected for processing (5)
  • config.json
  • src/index.js
  • src/modules/starboard.js
  • tests/index.test.js
  • tests/modules/starboard.test.js
📝 Walkthrough

Walkthrough

Implements a Discord starboard feature that automatically reposts messages to a dedicated channel when they receive a configurable number of star reactions. Includes configuration schema, database migration, event listeners, embed generation, and comprehensive test coverage.

Changes

Cohort / File(s) Summary
Configuration & Database
config.json, migrations/002_starboard-posts.cjs
Added starboard config object with enabled, channelId, threshold, emoji, selfStarAllowed, and ignoredChannels settings. New migration creates starboard_posts table to track source and starboard messages with metadata.
Core Starboard Module
src/modules/starboard.js
New module implementing starboard functionality: embeds with source message details, database operations (find/insert/update/delete posts), reaction event handlers for add/remove, star counting with self-star handling, and error logging.
Event Integration
src/index.js, src/modules/events.js
Added GuildMessageReactions intent to Discord client. New registerReactionHandlers function sets up messageReactionAdd/messageReactionRemove listeners; integrated into event lifecycle with starboard config checks and logging.
Test Coverage
tests/modules/events.test.js, tests/modules/starboard.test.js
Added tests for reaction handler registration and event behavior. Comprehensive starboard test suite covering config resolution, embed building, database operations, star counting, and reaction add/remove scenarios with mocked dependencies.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main feature: a starboard system to showcase popular messages, directly corresponding to the primary changeset.
Description check ✅ Passed The description thoroughly explains the starboard feature implementation, listing all included components, config options, behavior, and test coverage, fully related to the changeset.
Linked Issues check ✅ Passed The PR fully implements all coding requirements from issue #48: config structure, reaction listeners, gold-themed embed, deduplication via DB, star counting with self-star prevention, attachment handling, and removal logic.
Out of Scope Changes check ✅ Passed All changes are in-scope: migrations, starboard module, events wiring, config, and tests directly support issue #48; only one incidental GuildMessageReactions intent addition to enable the core feature.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/starboard

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link

greptile-apps bot commented Feb 26, 2026

Greptile Summary

This PR introduces a complete starboard feature that automatically reposts popular messages to a dedicated channel when they receive enough reactions.

Key changes:

  • Added starboard_posts table migration with proper deduplication via UNIQUE constraint on source_message_id
  • Implemented full starboard module (src/modules/starboard.js) with reaction handlers, embed building, and database operations
  • Wired reaction event listeners (MessageReactionAdd / MessageReactionRemove) in events module with proper partial handling
  • Added required Discord intents (GuildMessageReactions) and partials (Message, Reaction) for uncached messages
  • Default wildcard emoji (*) allows any emoji to trigger starboard, or can be configured to specific emoji
  • Comprehensive test coverage: 29 starboard tests + 6 events tests, all 1573 tests passing

Notable features:

  • Self-star prevention (configurable)
  • Handles message/reaction partials correctly
  • Uses safeSend for mention sanitization
  • Recovery logic when starboard messages are manually deleted
  • Ignored channels support
  • Proper error handling and logging throughout

The implementation is robust with good edge case handling. A few style improvements suggested around custom emoji configuration clarity and consistency.

Confidence Score: 4/5

  • This PR is safe to merge with minor style improvements recommended
  • Score reflects solid implementation with comprehensive tests (35 new tests, 100% coverage), proper error handling, correct use of Discord.js partials/intents, and safe database operations using parameterized queries. The few issues noted are style/consistency improvements (attachment fallback code, feedback loop check consistency, custom emoji docs) rather than functional bugs. The already-flagged issues from previous review threads (guild variable logic, unused variables, documentation updates) should be addressed but don't impact runtime safety.
  • No files require special attention beyond addressing the previous review comments about documentation updates (AGENTS.md, README.md) and the guild variable logic issues in src/modules/events.js

Important Files Changed

Filename Overview
migrations/002_starboard-posts.cjs Added starboard_posts table with UNIQUE constraint on source_message_id, uses parameterized queries, proper up/down migrations
src/modules/starboard.js Comprehensive starboard implementation with proper error handling, uses safeSend, handles partials, implements wildcard emoji support; minor edge case with custom emoji configuration format
src/modules/events.js Reaction handlers properly check bot reactions, fetch partials, verify guild context, and include error handling; events wiring is correct
src/index.js Added required GuildMessageReactions intent and Message/Reaction partials for uncached reaction events

Sequence Diagram

sequenceDiagram
    participant User
    participant Discord
    participant EventHandler
    participant Starboard
    participant DB
    participant StarboardChannel

    User->>Discord: Reacts to message with ⭐
    Discord->>EventHandler: MessageReactionAdd event
    EventHandler->>EventHandler: Check bot reaction, fetch partials
    EventHandler->>EventHandler: Verify guild context & config
    EventHandler->>Starboard: handleReactionAdd()
    Starboard->>Starboard: Check feedback loop, ignored channels
    Starboard->>Starboard: getStarCount() (with self-star exclusion)
    alt Star count >= threshold
        Starboard->>DB: findStarboardPost()
        alt Existing post
            Starboard->>StarboardChannel: Fetch & edit message
            Starboard->>DB: updateStarboardPostCount()
        else New post
            Starboard->>StarboardChannel: safeSend() embed
            Starboard->>DB: insertStarboardPost()
        end
    end

    User->>Discord: Removes reaction
    Discord->>EventHandler: MessageReactionRemove event
    EventHandler->>Starboard: handleReactionRemove()
    Starboard->>DB: findStarboardPost()
    alt Post exists
        Starboard->>Starboard: getStarCount()
        alt Below threshold
            Starboard->>StarboardChannel: Delete message
            Starboard->>DB: deleteStarboardPost()
        else Above threshold
            Starboard->>StarboardChannel: Update message
            Starboard->>DB: updateStarboardPostCount()
        end
    end
Loading

Last reviewed commit: 980114f

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

8 files reviewed, 11 comments

Edit Code Review Agent Settings | Greptile

Copy link

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Review Summary — 5 issues found

🔴 Critical (1)

  1. Missing GuildMessageReactions intent + Partials config (src/index.js): The client doesn't declare GatewayIntentBits.GuildMessageReactions, so reaction events will never fire — the entire starboard feature is silently non-functional. Additionally, Partials.Message, Partials.Channel, and Partials.Reaction are needed for the partial-handling code to work on uncached messages.

🟡 Warning (3)

  1. Starboard channel feedback loop (src/modules/starboard.js:243): No guard prevents starring starboard embeds themselves. Starring an embed creates a new starboard post for it, potentially cascading.
  2. Dead variable with confusing precedence (src/modules/events.js:232-242): The guild variable is always null due to ??/ternary precedence. Works by accident but is misleading. Same issue duplicated in the remove handler.
  3. Unbounded reaction.users.fetch() (src/modules/starboard.js:191): No limit parameter — could page through all users on popular messages.

🔵 Nitpick (1)

  1. Redundant index (migrations/002_starboard-posts.cjs:21): source_message_id UNIQUE constraint already creates an index. Consider indexing guild_id instead.

📝 Documentation

  1. Missing AGENTS.md / README.md updates: Per project conventions, new modules must be added to the Key Files table in AGENTS.md and documented in README.md.

coderabbitai[bot]
coderabbitai bot previously approved these changes Feb 26, 2026
Copy link

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Review Summary — 3 issues found

🔴 Critical (1)

  1. Missing GuildMessageReactions intent + Partials config (src/index.js:100-108): The client doesn't declare GatewayIntentBits.GuildMessageReactions, so reaction events will never fire — the entire starboard feature is silently non-functional. Additionally, Partials.Message, Partials.Channel, and Partials.Reaction are needed for the partial-handling code to work on uncached messages.

🟡 Warning (1)

  1. Unbounded reaction.users.fetch() consideration (src/modules/starboard.js:191): The { limit: 100 } is already present, but a comment documenting the intentional trade-off (self-star check misses authors beyond 100 reactions) would help future maintainers.

🔵 Nitpick (1)

  1. Missing startup log for starboard (src/modules/events.js): Other features (welcome, AI, moderation) log at startup in registerReadyHandler; starboard should too for consistency.

✅ What's solid

  • Core starboard logic is well-structured with proper error handling, partial message support, and feedback loop prevention
  • Comprehensive test coverage (35 new tests)
  • DB queries are parameterized (no SQL injection)
  • Winston logger used throughout (no console.*)
  • JSDoc on all exported functions
  • Config follows existing getConfig() per-request pattern

📝 Note on previous review comments

  • The Greptile review flagged a guild resolution logic error in events.js lines 232-234 / 260-262. Looking at the current code (commit e43cbc1), this has already been fixed — the logic is now correct (const guild = reaction.message.guild; if (!guild && reaction.message.partial) ...).
  • The redundant index issue in the migration has also been fixed (line 21 now has a comment explaining why no explicit index is needed).

Blocking issue

The intent/partials fix in src/index.js is the only blocking issue. Everything else is optional.

Copy link

@claude claude bot left a comment

Choose a reason for hiding this comment

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

3 issues found. See inline comments. Blocking: Missing GuildMessageReactions intent in src/index.js — reaction events will never fire. See review summary in PR comment.

Copy link

@claude claude bot left a comment

Choose a reason for hiding this comment

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

2 issues found. 🔴 Critical: Missing Partials configuration in src/index.js — without Partials.Message/Channel/Reaction, Discord.js won't emit reaction events for uncached messages, making starboard dead code for older messages. 🟡 Warning: Missing AGENTS.md and README.md documentation updates per project conventions. See inline comments for details and fix instructions.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/modules/starboard.js`:
- Around line 175-204: The self-star detection in getStarCount currently fetches
only the first 100 users via reaction.users.fetch({ limit: 100 }) which can miss
the author for reactions >100; update getStarCount to paginate through
reaction.users.fetch using the `after` cursor (or fetch in chunks) until either
the author ID is found or no more users remain, then subtract one if found;
alternatively, document the limitation if you intentionally keep the 100-limit
(add a clear comment near the reaction.users.fetch call explaining it may miss
authors beyond the first 100 users).

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d8e82c5 and e90af4e.

📒 Files selected for processing (7)
  • config.json
  • migrations/002_starboard-posts.cjs
  • src/index.js
  • src/modules/events.js
  • src/modules/starboard.js
  • tests/modules/events.test.js
  • tests/modules/starboard.test.js
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Greptile Review
  • GitHub Check: claude-review
🧰 Additional context used
📓 Path-based instructions (4)
**/*.js

📄 CodeRabbit inference engine (AGENTS.md)

**/*.js: Use ESM modules only — use import/export, never require()
Use node: protocol for Node.js builtins (e.g. import { readFileSync } from 'node:fs')
Always use semicolons
Use single quotes for strings
Use 2-space indentation
No TypeScript — use plain JavaScript with JSDoc comments for documentation

Files:

  • src/modules/events.js
  • tests/modules/starboard.test.js
  • tests/modules/events.test.js
  • src/index.js
  • src/modules/starboard.js
src/**/*.js

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.js: Always use Winston for logging — import { info, warn, error } from ../logger.js
NEVER use console.log, console.warn, console.error, or any console.* method in src/ files
Pass structured metadata to Winston logging calls (e.g. info('Message processed', { userId, channelId }))
Use custom error classes from src/utils/errors.js for error handling
Always log errors with context before re-throwing
Use getConfig(guildId?) from src/modules/config.js to read config
Use setConfigValue(path, value, guildId?) from src/modules/config.js to update config at runtime
Use splitMessage() utility for messages exceeding Discord's 2000-character limit
Use safeSend() wrapper for outgoing Discord messages to sanitize mentions and enforce allowedMentions

Files:

  • src/modules/events.js
  • src/index.js
  • src/modules/starboard.js
src/modules/events.js

📄 CodeRabbit inference engine (AGENTS.md)

Register event handlers in src/modules/events.js by calling client.on() with the event name and handler function

Files:

  • src/modules/events.js
tests/**/*.js

📄 CodeRabbit inference engine (AGENTS.md)

Test files must achieve at least 80% code coverage on statements, branches, functions, and lines

Files:

  • tests/modules/starboard.test.js
  • tests/modules/events.test.js
🧠 Learnings (6)
📚 Learning: 2026-02-25T02:39:33.506Z
Learnt from: CR
Repo: VolvoxLLC/volvox-bot PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-25T02:39:33.506Z
Learning: Applies to src/modules/events.js : Register event handlers in `src/modules/events.js` by calling `client.on()` with the event name and handler function

Applied to files:

  • src/modules/events.js
  • tests/modules/events.test.js
📚 Learning: 2026-02-25T02:39:33.506Z
Learnt from: CR
Repo: VolvoxLLC/volvox-bot PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-25T02:39:33.506Z
Learning: Applies to src/modules/{ai,spam,moderation}.js : Per-request modules (AI, spam, moderation) should call `getConfig(interaction.guildId)` on every invocation for automatic hot-reload support

Applied to files:

  • src/modules/events.js
  • tests/modules/events.test.js
📚 Learning: 2026-02-25T02:39:33.506Z
Learnt from: CR
Repo: VolvoxLLC/volvox-bot PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-25T02:39:33.506Z
Learning: Applies to src/**/*.js : Use `safeSend()` wrapper for outgoing Discord messages to sanitize mentions and enforce allowedMentions

Applied to files:

  • src/modules/events.js
📚 Learning: 2026-02-25T02:39:33.506Z
Learnt from: CR
Repo: VolvoxLLC/volvox-bot PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-25T02:39:33.506Z
Learning: Applies to src/**/*.js : Use `getConfig(guildId?)` from `src/modules/config.js` to read config

Applied to files:

  • tests/modules/events.test.js
📚 Learning: 2026-02-25T02:39:33.506Z
Learnt from: CR
Repo: VolvoxLLC/volvox-bot PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-25T02:39:33.506Z
Learning: Update `AGENTS.md` whenever finding new pitfalls or adding features that affect AI agent context

Applied to files:

  • src/modules/starboard.js
📚 Learning: 2026-02-25T02:39:33.506Z
Learnt from: CR
Repo: VolvoxLLC/volvox-bot PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-25T02:39:33.506Z
Learning: Update `config.json` documentation in README.md when adding new config sections or keys

Applied to files:

  • src/modules/starboard.js
🧬 Code graph analysis (4)
src/modules/events.js (2)
src/modules/config.js (6)
  • client (161-161)
  • client (522-522)
  • client (526-529)
  • client (711-711)
  • getConfig (282-313)
  • err (94-94)
src/modules/starboard.js (3)
  • reaction (176-176)
  • handleReactionAdd (215-309)
  • handleReactionRemove (320-389)
tests/modules/starboard.test.js (2)
src/db.js (1)
  • getPool (142-147)
src/modules/starboard.js (10)
  • resolveStarboardConfig (162-164)
  • buildStarboardEmbed (33-81)
  • findStarboardPost (89-101)
  • insertStarboardPost (114-128)
  • updateStarboardPostCount (137-143)
  • deleteStarboardPost (151-154)
  • getStarCount (175-204)
  • reaction (176-176)
  • handleReactionAdd (215-309)
  • handleReactionRemove (320-389)
tests/modules/events.test.js (2)
src/modules/events.js (1)
  • registerReactionHandlers (232-286)
src/modules/starboard.js (3)
  • reaction (176-176)
  • handleReactionAdd (215-309)
  • handleReactionRemove (320-389)
src/modules/starboard.js (4)
src/db.js (1)
  • getPool (142-147)
src/modules/config.js (1)
  • err (94-94)
src/utils/debugFooter.js (1)
  • r (305-305)
src/logger.js (3)
  • debug (223-225)
  • warn (237-239)
  • info (230-232)
🔇 Additional comments (21)
src/index.js (1)

107-107: LGTM!

Adding GatewayIntentBits.GuildMessageReactions is required to receive MessageReactionAdd and MessageReactionRemove events for the starboard feature. Correctly placed with the other intents.

migrations/002_starboard-posts.cjs (1)

1-27: LGTM!

The migration correctly creates the starboard_posts table with appropriate schema:

  • UNIQUE constraint on source_message_id provides the implicit index needed for efficient lookups
  • ON CONFLICT handling in the module's insertStarboardPost aligns with this constraint
  • Defensive IF NOT EXISTS / IF EXISTS clauses for idempotency
config.json (1)

98-105: LGTM!

Sensible default configuration:

  • enabled: false ensures the feature is opt-in
  • threshold: 3 is a reasonable minimum for community engagement
  • selfStarAllowed: false prevents gaming the system
  • All fields align with STARBOARD_DEFAULTS in the module
tests/modules/events.test.js (3)

31-34: LGTM!

Proper mock setup for the starboard module with both reaction handlers returning resolved promises.


413-493: Good test coverage for registerReactionHandlers.

The tests properly cover:

  • Event registration verification
  • Bot reaction filtering
  • Starboard disabled state handling
  • Delegation to handleReactionAdd / handleReactionRemove
  • Error handling (graceful failure without throwing)

543-544: LGTM!

Correctly verifies that registerEventHandlers wires both reaction events.

src/modules/events.js (4)

17-17: LGTM!

Import aligns with the module's public API.


60-65: LGTM!

Startup logging for starboard follows the established pattern for other features (welcome, AI, moderation), providing useful context with channelId and threshold.


224-286: Well-structured reaction handlers.

Good implementation:

  • Bot reactions correctly filtered early (line 235, 262)
  • Partial message fetching handles uncached messages (lines 238-244, 264-270)
  • Per-guild config resolution via getConfig(guildId) enables hot-reload support (lines 248, 274) — aligns with learned pattern
  • Error handling with structured metadata (lines 253-258, 279-284)
  • Early returns for disabled starboard prevent unnecessary processing

315-315: LGTM!

Correctly wires reaction handlers into the event registration flow.

tests/modules/starboard.test.js (5)

1-29: LGTM!

Clean test setup with proper mocks for logger and database modules, followed by imports of the starboard module's public API.


30-88: Well-designed test helpers.

The factory functions (mockPool, makeMockMessage, makeStarboardConfig, makeMockReaction) provide clean abstractions that make tests readable and maintainable.


92-328: Comprehensive unit tests for core functions.

Good coverage of:

  • resolveStarboardConfig default merging
  • buildStarboardEmbed with various message states (content, no content, attachments, embeds, missing author)
  • DB operations with correct SQL verification
  • getStarCount with self-star handling and edge cases

330-553: Thorough handleReactionAdd test coverage.

Tests cover the critical flows:

  • Disabled starboard
  • Non-matching emoji
  • Ignored channels
  • Self-star prevention
  • Below-threshold handling
  • New post creation
  • Existing post updates
  • Partial reaction fetching

555-677: Good handleReactionRemove test coverage.

Tests verify:

  • Disabled starboard handling
  • No-op when no existing post
  • Deletion when falling below threshold
  • Count updates when still above threshold
src/modules/starboard.js (6)

1-22: LGTM!

Clean module header with appropriate imports and well-documented defaults that align with config.json.


33-81: Robust embed builder implementation.

Good defensive coding:

  • Null-safe author name fallback chain (displayName ?? username ?? 'Unknown')
  • Handles both Discord.js Collection .find() and plain Map iteration for attachments
  • Falls back to embed images when no image attachment exists

89-154: LGTM on database helpers.

  • findStarboardPost: Properly catches errors and returns null to avoid breaking the flow
  • insertStarboardPost: Uses ON CONFLICT ... DO UPDATE for safe upsert behavior
  • updateStarboardPostCount / deleteStarboardPost: Straightforward operations

162-164: LGTM!

Simple spread merge provides expected override behavior.


215-309: Well-structured reaction add handler.

Good implementation details:

  • Early returns for disabled/misconfigured starboard
  • Partial fetch handling with graceful failure
  • Feedback loop prevention (ignoring starboard channel reactions)
  • Self-star check before counting
  • Threshold check before any Discord API calls
  • Fallback repost logic when existing starboard message was deleted (lines 279-290)

320-389: LGTM on reaction remove handler.

Properly handles both cases:

  • Below threshold → delete starboard post and DB record
  • Above threshold → update embed count

The debug level log for "already deleted" (line 364) is appropriate since this is an expected race condition.

Copy link

@claude claude bot left a comment

Choose a reason for hiding this comment

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

3 issues found (2 warnings, 1 nitpick). See inline comments for details.

🟡 Warning (2):

  1. Missing documentation updates (AGENTS.md + README.md): Per AGENTS.md §Documentation, new modules must update Key Files table, Database Tables section, and README.md config reference. src/modules/starboard.js, starboard_posts table, and starboard config are not documented.
  2. safeSend() not used (src/modules/starboard.js:300,311): Direct starboardChannel.send() calls should use safeSend() wrapper per project conventions.

🔵 Nitpick (1):
3. Silent return on missing channel (src/modules/starboard.js:376): handleReactionRemove silently returns when starboard channel not found — should log a warning for consistency with handleReactionAdd.

Previously flagged issues now resolved: Missing GuildMessageReactions intent ✅, missing Partials config ✅, dead guild variable in events.js ✅, redundant index in migration ✅, startup logging for starboard ✅.

Fix all issues with AI prompt
Fix the following issues in the volvox-bot starboard PR (branch: feat/starboard):

1. In `src/modules/starboard.js`:
   - Import `safeSend` from `'../utils/safeSend.js'`
   - Replace `starboardChannel.send(...)` on lines 300 and 311 with `safeSend(starboardChannel, ...)`
   - In `handleReactionRemove` around line 376, change the silent `if (!starboardChannel) return;` to:
     ```js
     if (!starboardChannel) {
       warn('Starboard channel not found', { channelId: sbConfig.channelId });
       return;
     }
     ```

2. In `AGENTS.md`:
   - Add `src/modules/starboard.js | Starboard — showcase popular messages in a dedicated channel` to the Key Files table
   - Add `starboard_posts | Starboard dedup tracking — maps source messages to starboard embeds` to the Database Tables section
   - Update Common Pitfall #3 to: "Discord intents — the bot needs MessageContent, GuildMembers, GuildVoiceStates, and GuildMessageReactions intents enabled"

3. In `README.md`, add a Starboard config section after Moderation and before Permissions:
   ### Starboard (`starboard`)
   | Key | Type | Description |
   |-----|------|-------------|
   | `enabled` | boolean | Enable starboard feature |
   | `channelId` | string | Channel to post starboard embeds |
   | `threshold` | number | Minimum star count to post (default: 3) |
   | `emoji` | string | Emoji to track, or `*` for any emoji (default: ⭐) |
   | `selfStarAllowed` | boolean | Allow message authors to star their own messages (default: false) |
   | `ignoredChannels` | string[] | Channel IDs to exclude from starboard |

Copy link

@claude claude bot left a comment

Choose a reason for hiding this comment

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

4 issues found (1 critical, 2 warnings, 1 nitpick). See inline comments for details.

🔴 Critical (1):

  1. Broken test (tests/modules/starboard.test.js:112): resolveStarboardConfig test expects emoji to be '⭐' but STARBOARD_DEFAULTS.emoji was changed to '*' in commit 3ec439f. This test will fail.

🟡 Warning (2):
2. Missing documentation (AGENTS.md + README.md): Per AGENTS.md §Documentation, new modules must update Key Files table, Database Tables section, Common Pitfalls, and README.md config reference.
3. safeSend() not used (src/modules/starboard.js:300,311): Direct starboardChannel.send() calls should use safeSend() wrapper per project conventions.

🔵 Nitpick (1):
4. Silent return on missing channel (src/modules/starboard.js:376): handleReactionRemove silently returns when starboard channel not found — should log a warning for consistency with handleReactionAdd.

Previously flagged issues now resolved: Missing GuildMessageReactions intent ✅, missing Partials config ✅, dead guild variable in events.js ✅, redundant index in migration ✅, startup logging ✅, feedback loop guard ✅.

Fix all issues with AI prompt
Fix the following issues in the volvox-bot starboard PR (branch: feat/starboard):

1. In `tests/modules/starboard.test.js` line 112:
   - Change `expect(result.emoji).toBe('⭐');` to `expect(result.emoji).toBe('*');`
   - STARBOARD_DEFAULTS.emoji was changed to '*' but this test wasn't updated

2. In `src/modules/starboard.js`:
   - Add import: `import { safeSend } from '../utils/safeSend.js';`
   - Line 300: Replace `starboardChannel.send({ content, embeds: [embed] })` with `safeSend(starboardChannel, { content, embeds: [embed] })`
   - Line 311: Replace `starboardChannel.send({ content, embeds: [embed] })` with `safeSend(starboardChannel, { content, embeds: [embed] })`
   - Line 376: Change `if (!starboardChannel) return;` to:
     ```js
     if (!starboardChannel) {
       warn('Starboard channel not found', { channelId: sbConfig.channelId });
       return;
     }
     ```

3. In `AGENTS.md`:
   - Add `src/modules/starboard.js | Starboard — showcase popular messages in a dedicated channel` to the Key Files table (after the events.js row)
   - Add `starboard_posts | Starboard dedup tracking — maps source messages to starboard embeds` to the Database Tables section
   - Update Common Pitfall #3 to: "Discord intents — the bot needs MessageContent, GuildMembers, GuildVoiceStates, and GuildMessageReactions intents enabled"

4. In `README.md`, add a Starboard config section after Moderation and before Permissions (around line 201):
   ### Starboard (`starboard`)

   | Key | Type | Description |
   |-----|------|-------------|
   | `enabled` | boolean | Enable starboard feature |
   | `channelId` | string | Channel to post starboard embeds |
   | `threshold` | number | Minimum star count to post (default: 3) |
   | `emoji` | string | Emoji to track, or `*` for any emoji (default: `*`) |
   | `selfStarAllowed` | boolean | Allow message authors to star their own messages (default: false) |
   | `ignoredChannels` | string[] | Channel IDs to exclude from starboard |

coderabbitai[bot]
coderabbitai bot previously approved these changes Feb 26, 2026
Copy link

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Review Summary — 4 issues found (1 critical, 2 warnings, 1 nitpick)

CI is failing — 3 test failures in starboard.test.js (lines 258, 280, 356).

🔴 Critical (1)

  1. Broken test expectations (tests/modules/starboard.test.js:258,280,356): Three getStarCount tests expect '*' (U+002A asterisk) for the emoji field, but the code returns '⭐' (U+2B50 star emoji). Confirmed failing in CI: AssertionError: expected '⭐' to be '*'.

🟡 Warning (2)

  1. Missing AGENTS.md documentation (AGENTS.md): Per §Documentation, src/modules/starboard.js must be added to the Key Files table, starboard_posts to the Database Tables section, and Common Pitfall #3 should mention GuildMessageReactions intent.
  2. Missing README.md documentation (README.md): New config sections require a README.md config reference (per config.json → README.md convention). No starboard section exists.

🔵 Nitpick (1)

  1. Silent return on missing channel (src/modules/starboard.js:377): handleReactionRemove silently returns when starboard channel not found — should log a warning for consistency with handleReactionAdd (line 282).

Previously flagged issues — now resolved ✅

  • Missing GuildMessageReactions intent ✅
  • Missing Partials config ✅
  • Dead guild variable in events.js ✅
  • Redundant index in migration ✅
  • Startup logging for starboard ✅
  • Feedback loop guard ✅
  • safeSend usage ✅
Fix all issues with AI prompt
Fix the following issues in the volvox-bot starboard PR (branch: feat/starboard):

1. In `tests/modules/starboard.test.js`:
   - Line 258: Change `expect(result.emoji).toBe('*');` to `expect(result.emoji).toBe('⭐');`
   - Line 280: Change `expect(result.emoji).toBe('*');` to `expect(result.emoji).toBe('⭐');`
   - Line 356: Change `expect(result.emoji).toBe('*');` to `expect(result.emoji).toBe('⭐');`
   These tests expect '*' (asterisk) but getStarCount returns '⭐' (star emoji)

2. In `src/modules/starboard.js` line 377:
   Change `if (!starboardChannel) return;` to:
   if (!starboardChannel) {
     warn('Starboard channel not found', { channelId: sbConfig.channelId });
     return;
   }

3. In `AGENTS.md`:
   - Add `src/modules/starboard.js | Starboard — showcase popular messages in a dedicated channel` to the Key Files table (after events.js row)
   - Add `starboard_posts | Starboard dedup tracking — maps source messages to starboard embeds` to the Database Tables section
   - Update Common Pitfall #3 to: "Discord intents — the bot needs MessageContent, GuildMembers, GuildVoiceStates, and GuildMessageReactions intents enabled"

4. In `README.md`, add a Starboard config section in the Configuration reference (after Moderation):
   ### Starboard (`starboard`)
   | Key | Type | Description |
   |-----|------|-------------|
   | `enabled` | boolean | Enable starboard feature |
   | `channelId` | string | Channel to post starboard embeds |
   | `threshold` | number | Minimum star count to post (default: 3) |
   | `emoji` | string | Emoji to track, or `*` for any emoji (default: `*`) |
   | `selfStarAllowed` | boolean | Allow message authors to star their own messages (default: false) |
   | `ignoredChannels` | string[] | Channel IDs to exclude from starboard |

… warn log

- Fix three test assertions that expected '*' instead of '⭐' for
  getStarCount return values (lines 258, 280, 356)
- Add warn log to handleReactionRemove when starboard channel not found
  (mirrors handleReactionAdd behavior)
Copy link

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Review Summary — 1 issue (documentation)

🟡 Warning (1)

Missing AGENTS.md and README.md documentation updates (src/modules/starboard.js): Per AGENTS.md §Documentation ("Keep docs up to date — this is non-negotiable"), new modules must update:

  1. AGENTS.md Key Files table — add src/modules/starboard.js | Starboard — showcase popular messages in a dedicated channel
  2. AGENTS.md Database Tables — add starboard_posts | Starboard dedup tracking — maps source messages to starboard embeds
  3. AGENTS.md Common Pitfall #3 — update to include GuildMessageReactions intent
  4. README.md Configuration reference — add a Starboard (starboard) config section (same format as AI, Triage, Welcome, Moderation)

✅ Previously flagged issues — all resolved

  • Missing GuildMessageReactions intent ✅
  • Missing Partials config ✅
  • Dead guild variable in events.js ✅
  • Redundant index in migration ✅
  • Startup logging for starboard ✅
  • Feedback loop guard ✅
  • safeSend usage ✅
  • Broken test assertions ✅
  • Missing warn log in handleReactionRemove

✅ CI status

All tests pass, lint clean.

Fix all issues with AI prompt
Fix the documentation gaps in the volvox-bot starboard PR (branch: feat/starboard):

1. In `AGENTS.md`:
   - After the `src/modules/events.js` row in the Key Files table (line 35), add:
     | `src/modules/starboard.js` | Starboard — showcase popular messages in a dedicated channel |
   - After the `mod_scheduled_actions` row in the Database Tables section (line 137), add:
     | `starboard_posts` | Starboard dedup tracking — maps source messages to starboard embeds |
   - Update Common Pitfall #3 (line 223) from:
     "Discord intents — the bot needs MessageContent, GuildMembers, and GuildVoiceStates intents enabled"
     to:
     "Discord intents — the bot needs MessageContent, GuildMembers, GuildVoiceStates, and GuildMessageReactions intents enabled"

2. In `README.md`, after the Moderation section (after line 203, before Permissions), add:

### Starboard (`starboard`)

| Key | Type | Description |
|-----|------|-------------|
| `enabled` | boolean | Enable starboard feature |
| `channelId` | string | Channel to post starboard embeds |
| `threshold` | number | Minimum star count to post (default: 3) |
| `emoji` | string | Emoji to track, or `*` for any emoji (default: `*`) |
| `selfStarAllowed` | boolean | Allow message authors to star their own messages (default: false) |
| `ignoredChannels` | string[] | Channel IDs to exclude from starboard |

@BillChirico
Copy link
Collaborator Author

🔧 PR Patrol sweep — Thu Feb 26 @ 2:45 PM

No code changes needed — all 31 starboard tests passing ✅

Threads resolved (6 total):

  • Critical resolved as stale — getStarCount wildcard tests pass correctly, CI failure no longer reproducible
  • Warning (docs gap) resolved — deferred to PR author
  • 4 nitpicks resolved

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.

Starboard — automatically showcase the best community messages

1 participant