Skip to content

refactor(bot): extract MessagePipeline handler chain - #981

Merged
LucasSantana-Dev merged 6 commits into
mainfrom
refactor/message-pipeline
May 23, 2026
Merged

LucasSantana-Dev merged 6 commits into
mainfrom
refactor/message-pipeline

Conversation

@LucasSantana-Dev

@LucasSantana-Dev LucasSantana-Dev commented May 23, 2026 •

Copy link
Copy Markdown
Owner

Summary

Implements T3 of the architecture refactor: Split the 322-LOC messageHandler into a handler chain pattern with stop-signal support.

Changes

  • MessagePipeline: Core runner with error isolation and stop-signal short-circuit
  • AutoModHandler: Violation detection (caps, links, invites, badwords)
  • SpamHandler: Spam detection (extracted from autoMod)
  • CustomCommandHandler: Command matching and tracking
  • XpHandler: XP/leveling system
  • Refactored entry point: 48 LOC (down from 322 LOC original)

Design Decisions

  1. Handler interface contract: All handlers implement canHandle() + handle() returning stop boolean
  2. Stop-signal semantics: First handler returning stop:true halts the pipeline (used by autoMod/spam to prevent further processing)
  3. Error isolation: Each handler execution wrapped in try-catch; one failure doesn't crash subsequent handlers
  4. Feature toggles injected via context: Avoid per-handler feature toggle service calls
  5. Pipeline registered at module load: Handlers execute in registration order (spam → autoMod → custom commands → xp)

Verification

  • TypeScript compilation: ✓ Passed
  • Test count: 6 dedicated pipeline tests + 2902 full suite tests ✓ Passed
  • Entry point LOC: 48 (target: <50) ✓ Met
  • No breaking changes: Backward compatible via handleMessageCreate() export

Summary by CodeRabbit

Release Notes

  • New Features

    • Automatic message moderation including filtering for excessive caps, links, invites, and inappropriate language.
    • Support for custom guild commands with configurable responses.
    • Member experience tracking with level-up notifications and role-based rewards.
    • Spam message detection and removal.
  • Tests

    • Comprehensive test coverage added for message handling functionality.

Review Change Stack

Split 322-LOC messageHandler into typed MessageHandler implementations:
- MessagePipeline runner with stop-signal short-circuit
- AutoModHandler (violation enforcement)
- SpamHandler (spam detection, extracted from autoMod)
- CustomCommandHandler (command matching)
- XpHandler (XP/leveling)

Each handler tested in isolation. Adding handlers requires no changes
to existing files.
@vercel

vercel Bot commented May 23, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lucky Ready Ready Preview, Comment May 23, 2026 10:26pm

Request Review

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@coderabbitai

coderabbitai Bot commented May 23, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

@LucasSantana-Dev, we couldn't start this review because you've used your available PR reviews for now.

Your plan currently allows 1 review/hour. Refill in 28 minutes and 30 seconds.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more review capacity refills, 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 trial, open-source, and free plans. In all cases, review capacity refills continuously over time.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fe60cd4f-6876-4f08-8c81-5366356731ae

📥 Commits

Reviewing files that changed from the base of the PR and between 0c2b225 and 271bf85.

📒 Files selected for processing (7)
  • packages/bot/src/handlers/__tests__/messageHandler.test.ts
  • packages/bot/src/handlers/message/__tests__/autoModHandler.test.ts
  • packages/bot/src/handlers/message/__tests__/customCommandHandler.test.ts
  • packages/bot/src/handlers/message/__tests__/spamHandler.test.ts
  • packages/bot/src/handlers/message/__tests__/xpHandler.test.ts
  • packages/bot/src/handlers/message/customCommandHandler.ts
  • packages/bot/src/handlers/messageHandler.ts
📝 Walkthrough

Walkthrough

This PR refactors Discord message handling from monolithic in-file implementations into a modular pipeline architecture. A new MessagePipeline class orchestrates typed MessageHandler implementations (spam, automod, custom commands, xp) that are executed sequentially per message with error isolation. The refactored handleMessageCreate builds guild-scoped feature toggles and context, then delegates to the pipeline instead of invoking handlers directly. Comprehensive tests validate all components.

Changes

Message Handler Pipeline & Modular Architecture

Layer / File(s) Summary
Message Handler Contracts
packages/bot/src/handlers/message/types.ts
Defines MessageHandler interface with async canHandle predicate and handle method, MessageHandlerResult with stop flag, and MessageContext containing guild, member, and feature toggles.
Pipeline Framework & Tests
packages/bot/src/handlers/message/pipeline.ts, packages/bot/src/handlers/message/__tests__/pipeline.test.ts
MessagePipeline registers and sequentially executes handlers with error isolation, handler skipping when canHandle returns false, and early termination on stop: true. Tests validate registration chaining, all-handler execution, stopping behavior, handler skipping, and error resilience in both canHandle and handle.
AutoMod Handler Implementation & Tests
packages/bot/src/handlers/message/autoModHandler.ts, packages/bot/src/handlers/message/__tests__/autoModHandler.test.ts
Filters on AUTOMOD toggle and non-bot authors, loads guild settings, skips exempt channels/roles, runs conditional violation checks (caps, links, invites, bad words), and applies moderation actions (warn, mute, kick, ban) via moderationService.createCase. Test suite covers canHandle filtering, early exits for null settings and exemptions, individual violation detection paths with mocked checks, and no-violation scenarios.
Spam Handler Implementation & Tests
packages/bot/src/handlers/message/spamHandler.ts, packages/bot/src/handlers/message/__tests__/spamHandler.test.ts
Filters on AUTOMOD toggle, non-bot authors, and spamEnabled in guild settings. Detects spam via trackMessageAndCheckSpam, deletes spam messages (best-effort), stops processing on spam, and continues on non-spam or errors. Tests validate canHandle filtering and handle outcomes for spam detection with message deletion verification.
Custom Command Handler Implementation & Tests
packages/bot/src/handlers/message/customCommandHandler.ts, packages/bot/src/handlers/message/__tests__/customCommandHandler.test.ts
Filters on CUSTOM_COMMANDS toggle and non-bot authors. Loads guild commands, matches message content (exact trigger or prefix + space), replies with command response and repliedUser: false, increments usage. Tests cover canHandle filtering and handle scenarios for no commands, no match, exact-trigger and prefix-trigger matches with args, and error handling.
XP Handler Implementation & Tests
packages/bot/src/handlers/message/xpHandler.ts, packages/bot/src/handlers/message/__tests__/xpHandler.test.ts
Skips bot authors, loads guild XP config, enforces cooldown, awards XP, optionally announces level-ups to a text channel, and conditionally grants role rewards. Tests validate canHandle for bot filtering and handle for disabled config, cooldown skipping, successful XP addition, level-up announcements, role rewards, and first-time XP.
Handler Orchestration & Module Exports
packages/bot/src/handlers/messageHandler.ts, packages/bot/src/handlers/message/index.ts
Refactors handleMessageCreate to build guild-scoped feature toggles and MessageContext, then execute a MessagePipeline with spam, automod, custom command, and xp handlers registered in order. Removes in-file AutoMod/Custom Commands/XP implementations. Introduces barrel export for pipeline, types, and handlers. Single outer error handler logs pipeline failures.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • LucasSantana-Dev/Lucky#401: Updates messageHandler.spec.ts to test handleMessageCreate behavior for AutoMod and Custom Commands feature toggles, aligning with the main PR's refactor of message handling into modular handlers.
  • LucasSantana-Dev/Lucky#378: Extends messageHandler.spec.ts to assert error handling when addXP/getRewards fail, directly targeting the XP flow in the main PR's refactored pipeline.
  • LucasSantana-Dev/Lucky#399: Introduces trackMessageAndCheckSpam and checkLinks(guildId, content, channelId) API signatures that the main PR's spamHandler and autoModHandler tests depend on.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly identifies the main change: refactoring message handling to extract and use a MessagePipeline handler chain pattern, which aligns with the substantial code reorganization described in the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/message-pipeline

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.

@github-actions

Copy link
Copy Markdown

Failed to generate code suggestions for PR

Cover each handler's canHandle/handle branches in isolation:
- AutoModHandler: violation types, exemptions, stop signal
- SpamHandler: spam detection, stop signal
- CustomCommandHandler: trigger matching, usage tracking
- XpHandler: cooldown, level-up, role rewards

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (4)
packages/bot/src/handlers/message/__tests__/pipeline.test.ts (2)

11-29: ⚡ Quick win

Test name says “order”, but it only checks chaining.

At Line 11, this test does not assert execution order; it only asserts register() fluency. Please execute the pipeline and assert handler1 runs before handler2.

Proposed test fix
-it('should register handlers in order', () => {
+it('should register handlers in order', async () => {
     const pipeline = new MessagePipeline()
@@
-    pipeline.register(handler1)
-    pipeline.register(handler2)
-
-    const result = pipeline.register(handler1)
+    const result = pipeline.register(handler1).register(handler2)
     expect(result).toBe(pipeline)
+
+    const message = { guild: { id: 'guild1' }, member: { id: 'member1' } } as unknown as Message
+    const context = {
+        guild: message.guild,
+        member: message.member,
+        featureToggles: {},
+    } as unknown as MessageContext
+
+    await pipeline.execute(message, context)
+    expect((handler1.handle as jest.Mock).mock.invocationCallOrder[0])
+        .toBeLessThan((handler2.handle as jest.Mock).mock.invocationCallOrder[0])
 })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/bot/src/handlers/message/__tests__/pipeline.test.ts` around lines 11
- 29, The test currently only checks that register() is chainable; update it to
actually run the pipeline and assert handler execution order: after registering
handler1 and handler2 on the MessagePipeline instance, invoke the pipeline
(e.g., await pipeline.execute(message) or await pipeline.handle(message) —
whichever the MessagePipeline API exposes) with a dummy message so both
handlers' canHandle/handle mocks run, then assert handler1.handle was called
before handler2.handle by comparing their mock invocation order (use
handler1.handle.mock.invocationCallOrder[0] <
handler2.handle.mock.invocationCallOrder[0]) and keep the existing chaining
assertion (expect(result).toBe(pipeline)).

125-185: ⚡ Quick win

Assert errorLog calls in the error-path tests.

At Line 125 and Line 156, error isolation is validated, but the expected logging side-effect is not. Add assertions so observability regressions are caught.

Proposed assertions
+import { errorLog } from '`@lucky/shared/utils`'
@@
+const errorLogMock = jest.mocked(errorLog)
+
 it('should isolate errors - one handler error does not crash pipeline', async () => {
@@
     await expect(pipeline.execute(message, context)).resolves.not.toThrow()
     expect(handler2.handle).toHaveBeenCalled()
+    expect(errorLogMock).toHaveBeenCalledWith(
+        expect.objectContaining({
+            message: expect.stringContaining('Handler1'),
+        }),
+    )
 })
@@
 it('should catch canHandle errors and continue', async () => {
@@
     await expect(pipeline.execute(message, context)).resolves.not.toThrow()
     expect(handler2.handle).toHaveBeenCalled()
+    expect(errorLogMock).toHaveBeenCalledWith(
+        expect.objectContaining({
+            message: expect.stringContaining('Handler1'),
+        }),
+    )
 })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/bot/src/handlers/message/__tests__/pipeline.test.ts` around lines
125 - 185, The tests for MessagePipeline error isolation need to also assert
that the pipeline logs errors; update both tests that create handler1 (the one
that throws in canHandle or handle) to spy/mock the pipeline's logger (errorLog
or the module logger used by MessagePipeline), run pipeline.execute(message,
context) as before, then add assertions that the logger.error / errorLog was
called with the handler name (handler1.name) and the thrown Error (or its
message) to validate observability; ensure the spy is cleared/restored after
each test.
packages/bot/src/handlers/message/__tests__/xpHandler.test.ts (1)

223-273: ⚡ Quick win

Add a reward test for level-up without announceChannel.

Current coverage validates rewards only when announceChannel exists. Add a case with leveledUp: true and no announceChannel that still expects context.member.roles.add(...) to run.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/bot/src/handlers/message/__tests__/xpHandler.test.ts` around lines
223 - 273, The test suite is missing a case that asserts role rewards are
applied when a user levels up but no announceChannel is configured; add a new
spec that mocks levelService.getConfig to return enabled:true and no
announceChannel (omit or set undefined), mock levelService.getMemberXP to allow
XP, mock levelService.addXP to resolve { leveledUp: true, newLevel: 5 }, mock
levelService.getRewards to include { level:5, roleId:'role5' }, call
xpHandler.handle(message, context) and assert context.member.roles.add was
called with 'role5' (use the same helpers/mocks as the existing test for
xpHandler.handle, levelService.getConfig, getMemberXP, addXP, getRewards and
context.member.roles.add).
packages/bot/src/handlers/message/__tests__/autoModHandler.test.ts (1)

153-318: ⚡ Quick win

Add a violation-path assertion for moderation side effects.

Current tests verify rule-check invocations but not the enforcement outcome (stop: true, message.delete(), and moderation action/case side effects). Adding one such test will catch regressions in the actual moderation flow.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/bot/src/handlers/message/__tests__/autoModHandler.test.ts` around
lines 153 - 318, Add a test that asserts enforcement side effects when a
violation is detected: stub autoModService.getSettings to enable one rule (e.g.,
capsEnabled:true), stub the corresponding check (e.g., autoModService.checkCaps)
to resolve true, spy/mock message.delete and the moderation side-effect API used
by the handler (e.g., moderationService.createCase or
moderationService.applyAction), then call autoModHandler.handle(message,
context) and assert result.stop is true,
expect(message.delete).toHaveBeenCalled(), and expect the moderation service
mock (createCase/applyAction) was called with the guild id/member and relevant
reason; reference autoModHandler.handle, autoModService.checkCaps (or
checkLinks/checkInvites/checkWords), message.delete, and
moderationService.createCase/applyAction to locate the code.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/bot/src/handlers/message/autoModHandler.ts`:
- Around line 58-62: The auto-mod stores every detected violation with action:
'delete' (see violations.push calls in autoModHandler) but the downstream switch
only handles 'warn'/'mute'/'kick'/'ban', so enforcement branches are never
reached; fix by either (A) setting the correct action value when pushing
violations (use 'warn'/'mute'/'kick'/'ban' as appropriate) or (B) adding a
'delete' branch to the enforcement switch (and call the existing
delete/moderation helper and createCase logic for deletes), and remove any dead
branches; update all violations.push occurrences (caps, spam, mention, link
detectors) and the enforcement switch in autoModHandler accordingly so actions
and handlers match.

In `@packages/bot/src/handlers/message/xpHandler.ts`:
- Around line 49-67: The role reward logic is incorrectly nested under the
announceChannel check so rewards only run when announcements are enabled; change
the flow in the leveled-up branch (where result.leveledUp is checked) to first,
if config.announceChannel is set then fetch the channel and send the message
(using message.client.channels.fetch and TextChannel.send as currently written),
and separately (not nested under announceChannel) call
levelService.getRewards(guildId), find the matching reward for result.newLevel,
and call context.member.roles.add(reward.roleId) as before; ensure you still
guard optional operations with .catch(() => {}) and null-checks on
context.member so reward granting runs regardless of announceChannel.

In `@packages/bot/src/handlers/messageHandler.ts`:
- Around line 22-31: The two feature toggle lookups
(featureToggleService.isEnabled for 'AUTOMOD' and 'CUSTOM_COMMANDS' that
populate featureToggles) currently run with awaits that can reject and
short-circuit pipeline.execute; change to resolve each lookup independently and
default failures to false (e.g., use Promise.allSettled or individual try/catch
around each featureToggleService.isEnabled call) so that any rejection only sets
that toggle to false and does not prevent calling pipeline.execute or other
handlers like AutoMod/spam/XP.

---

Nitpick comments:
In `@packages/bot/src/handlers/message/__tests__/autoModHandler.test.ts`:
- Around line 153-318: Add a test that asserts enforcement side effects when a
violation is detected: stub autoModService.getSettings to enable one rule (e.g.,
capsEnabled:true), stub the corresponding check (e.g., autoModService.checkCaps)
to resolve true, spy/mock message.delete and the moderation side-effect API used
by the handler (e.g., moderationService.createCase or
moderationService.applyAction), then call autoModHandler.handle(message,
context) and assert result.stop is true,
expect(message.delete).toHaveBeenCalled(), and expect the moderation service
mock (createCase/applyAction) was called with the guild id/member and relevant
reason; reference autoModHandler.handle, autoModService.checkCaps (or
checkLinks/checkInvites/checkWords), message.delete, and
moderationService.createCase/applyAction to locate the code.

In `@packages/bot/src/handlers/message/__tests__/pipeline.test.ts`:
- Around line 11-29: The test currently only checks that register() is
chainable; update it to actually run the pipeline and assert handler execution
order: after registering handler1 and handler2 on the MessagePipeline instance,
invoke the pipeline (e.g., await pipeline.execute(message) or await
pipeline.handle(message) — whichever the MessagePipeline API exposes) with a
dummy message so both handlers' canHandle/handle mocks run, then assert
handler1.handle was called before handler2.handle by comparing their mock
invocation order (use handler1.handle.mock.invocationCallOrder[0] <
handler2.handle.mock.invocationCallOrder[0]) and keep the existing chaining
assertion (expect(result).toBe(pipeline)).
- Around line 125-185: The tests for MessagePipeline error isolation need to
also assert that the pipeline logs errors; update both tests that create
handler1 (the one that throws in canHandle or handle) to spy/mock the pipeline's
logger (errorLog or the module logger used by MessagePipeline), run
pipeline.execute(message, context) as before, then add assertions that the
logger.error / errorLog was called with the handler name (handler1.name) and the
thrown Error (or its message) to validate observability; ensure the spy is
cleared/restored after each test.

In `@packages/bot/src/handlers/message/__tests__/xpHandler.test.ts`:
- Around line 223-273: The test suite is missing a case that asserts role
rewards are applied when a user levels up but no announceChannel is configured;
add a new spec that mocks levelService.getConfig to return enabled:true and no
announceChannel (omit or set undefined), mock levelService.getMemberXP to allow
XP, mock levelService.addXP to resolve { leveledUp: true, newLevel: 5 }, mock
levelService.getRewards to include { level:5, roleId:'role5' }, call
xpHandler.handle(message, context) and assert context.member.roles.add was
called with 'role5' (use the same helpers/mocks as the existing test for
xpHandler.handle, levelService.getConfig, getMemberXP, addXP, getRewards and
context.member.roles.add).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 10644abb-66b1-44dd-8c89-6d4468225047

📥 Commits

Reviewing files that changed from the base of the PR and between c3192c3 and 0c2b225.

📒 Files selected for processing (13)
  • packages/bot/src/handlers/message/__tests__/autoModHandler.test.ts
  • packages/bot/src/handlers/message/__tests__/customCommandHandler.test.ts
  • packages/bot/src/handlers/message/__tests__/pipeline.test.ts
  • packages/bot/src/handlers/message/__tests__/spamHandler.test.ts
  • packages/bot/src/handlers/message/__tests__/xpHandler.test.ts
  • packages/bot/src/handlers/message/autoModHandler.ts
  • packages/bot/src/handlers/message/customCommandHandler.ts
  • packages/bot/src/handlers/message/index.ts
  • packages/bot/src/handlers/message/pipeline.ts
  • packages/bot/src/handlers/message/spamHandler.ts
  • packages/bot/src/handlers/message/types.ts
  • packages/bot/src/handlers/message/xpHandler.ts
  • packages/bot/src/handlers/messageHandler.ts

Comment thread packages/bot/src/handlers/message/autoModHandler.ts
Comment thread packages/bot/src/handlers/message/xpHandler.ts
Comment thread packages/bot/src/handlers/messageHandler.ts Outdated

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@sonarqubecloud

Copy link
Copy Markdown

@LucasSantana-Dev
LucasSantana-Dev merged commit bfcf438 into main May 23, 2026
31 of 32 checks passed
@LucasSantana-Dev
LucasSantana-Dev deleted the refactor/message-pipeline branch May 23, 2026 22:38
LucasSantana-Dev added a commit that referenced this pull request May 24, 2026
## Summary

Replaces the 15+ positional arguments passed through the autoplay
collector pipeline with a single `AutoplayContext` value object,
improving call-site clarity and making the pipeline easier to extend.

### Changes
- Introduce `AutoplayContext` interface in `autoplayContext.ts`
- Update `candidateCollector`, `lastFmSeeder`, `spotifyRecommender`,
`replenisher`, and `candidateFallback` to accept `AutoplayContext`
instead of positional args
- Fix missing `beforeEach` mock setup in `candidateCollector` tests
- Remove leftover `.bak` file from refactor

### Why
Positional argument lists of 15+ items are hard to read, easy to
misorder, and brittle to extend. A named value object surfaces intent at
every call site and isolates future additions to one interface
definition.

Part of the architecture refactor series (T1–T5):
- T1 #979 ✅ — extract `MessagePipeline`
- T2 #980 ✅ — introduce `IGuildAutomationRepository`
- T3 #981 ✅ — `AutomationPlan` result type
- T4 #982 ✅ — `GuildAutomationRepository` / `Orchestrator` split
- T5 (this PR) — `AutoplayContext` value object
@LucasSantana-Dev
LucasSantana-Dev restored the refactor/message-pipeline branch May 24, 2026 15:18
LucasSantana-Dev added a commit that referenced this pull request May 24, 2026
ADRs for the 5 refactors merged in PRs #979–#983 and the Phase 4 test
reduction strategy.

## Decision records added

- `2026-05-23-artist-suggestion-service.md` — ArtistSuggestionService
extraction (#980)
- `2026-05-23-autoplay-context-value-object.md` — AutoplayContext value
object (#983)
- `2026-05-23-bot-test-reduction-phase4-replacement-strategy.md` — Phase
4 test replacement strategy
- `2026-05-23-guild-automation-orchestrator-repository-split.md` —
GuildAutomationService split (#982)
- `2026-05-23-message-pipeline-handler-chain.md` — MessagePipeline
handler chain (#981)
- `2026-05-23-recommendation-engine-single-entrypoint.md` —
recommendTracks() single entrypoint (#979)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Added architecture decision records documenting planned service
refactoring, test optimization strategies, and API consolidation
initiatives to improve system maintainability.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/LucasSantana-Dev/Lucky/pull/1040?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
LucasSantana-Dev added a commit that referenced this pull request May 25, 2026
## Summary

- Bumps all package.json files from `2.14.1` → `2.15.0`
- Populates `CHANGELOG.md` with everything since v2.14.1
- Adds ADR `docs/decisions/2026-05-24-ci-runtime-baseline-accepted.md`
(CI runtime baseline: 3–4 min accepted, Jest sharding deferred)

### Changes included in this release

**Added**
- ServerLogs + ServerSettings UI pages (#965)
- AutoMessages executor wiring into execution service (#950)

**Changed**
- 4 UI redesigns: Admin, Config, Login, ServersPage, CustomCommands,
GuildAutomation, Spotify, LastFm (#967–#970)
- 5 refactors: AutoplayContext VO (#983),
GuildAutomationOrchestrator/Repository split (#982), MessagePipeline
chain (#981), ArtistSuggestionService (#980), recommendTracks entrypoint
(#979)

**Fixed** — deploy CI gap sweep (A–F)
- Gap A: hard-fail on OAuth 429 (#1045)
- Gap B: surface async deploy via commit statuses (#1046)
- Gap C: bot healthcheck polls Discord gateway, not Redis TCP (#1047)
- Gap D: post error status on lock contention (#1052)
- Gap E: add bot to required containers, remove dead unhealthy grep
(#1054)
- Gap F: wait for homelab-deploy completion on docker_rebuilt=true path
(#1056)
- lockfile-hash BuildKit cache key (#1016)
- squash-merged release branch archive (#946)

**Internal**
- Phase 4 test cleanup — 93 tests removed (#956–#1035)
- Pre-commit hooks: husky + lint-staged + tsc (#1007)
- madge gate promoted to blocking
- Dependabot routine bumps (#971–#977, #1042)

> **Note:** #1054 (Gap E) may still be in CI — merge this PR after #1054
lands.

This branch was successfully deployed

1 active deployment
Preview — 271bf85e Deployed May 23, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant