Skip to content

fix(bot): deduplicate same-song versions in autoplay - #569

Merged
LucasSantana-Dev merged 5 commits into
mainfrom
fix/autoplay-dedup-same-song-versions
Apr 12, 2026
Merged

LucasSantana-Dev merged 5 commits into
mainfrom
fix/autoplay-dedup-same-song-versions

Conversation

@LucasSantana-Dev

@LucasSantana-Dev LucasSantana-Dev commented Apr 12, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Keys autoplay candidates by normalized title+author instead of URL — prevents duplicate versions (Official, Remastered, Live) from both entering the candidate pool
  • Adds title-key dedup in selectDiverseCandidates as belt-and-suspenders
  • Fixes HYPHENATED_VERSION_SUFFIX regex to handle year-suffix and Original Mix patterns

Root cause

upsertScoredCandidate used track.url as map key. Two YouTube videos of the same song had different URLs → both entered candidates → both could be selected in the same replenish.

Test plan

  • cleanTitle("Song - Remastered 2011") → "Song"
  • cleanTitle("Song - 2024") → "Song"
  • cleanTitle("Song - Original Mix") → "Song"
  • Two versions of same song in search results → only 1 added to queue
  • All existing 1958 tests pass

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved duplicate-song detection when adding tracks to the queue by de-duplicating by normalized title/author and preventing multiple title variants from being added.
    • Enhanced search query cleaning to strip more hyphenated suffixes (remasters with years, original mixes/versions, standalone years, and other common tags).
  • Tests

    • Added tests validating deduplication of same-song variants during queue addition.
    • Added tests covering the expanded suffix-cleaning behavior.

@vercel

vercel Bot commented Apr 12, 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 Apr 12, 2026 3:24am

@github-actions github-actions Bot added the bot label Apr 12, 2026
@coderabbitai

coderabbitai Bot commented Apr 12, 2026 •

Copy link
Copy Markdown

Warning

Rate limit exceeded

@LucasSantana-Dev has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 3 minutes and 37 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 3 minutes and 37 seconds.

⌛ 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.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cc0aaaf6-f0fd-4fdc-8c11-cdff65e8c289

📥 Commits

Reviewing files that changed from the base of the PR and between 57b30cc and d4adbc8.

📒 Files selected for processing (2)
  • packages/bot/src/utils/music/queueManipulation.ts
  • packages/bot/src/utils/music/searchQueryCleaner.ts
📝 Walkthrough

Walkthrough

Changed queue candidate upsert/selection to use normalized title/author heuristics and enforce title-level deduplication; expanded hyphenated version-suffix patterns in search title cleaning; added tests validating deduplication and new suffix-cleaning behaviors.

Changes

Cohort / File(s) Summary
Queue Deduplication Logic
packages/bot/src/utils/music/queueManipulation.ts
Changed upsertScoredCandidate to key candidates by a heuristic normalized title+author (fallback to previous key if normalized key is short). Added title-level deduplication in selectDiverseCandidates via selectedTitleKeys and normalizeTitleOnly.
Queue Deduplication Tests
packages/bot/src/utils/music/queueManipulation.spec.ts
Added Jest tests under addSelectedTracks async writes that mock search results with multiple URL/title variants of the same song and assert only a single variant is added.
Search Title Cleaning Logic
packages/bot/src/utils/music/searchQueryCleaner.ts
Replaced single hyphenated-suffix regex with HYPHENATED_VERSION_SUFFIXES array and isVersionSuffix; recognizes remaster patterns with optional year, bare four-digit years, `official audio
Search Title Cleaning Tests
packages/bot/src/utils/music/searchQueryCleaner.spec.ts
Extended cleanTitle tests to assert removal of hyphenated remaster-with-year, year-only, and Original Mix/Original Version suffixes, plus a control case for unchanged normal titles.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

bot, size/m

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly summarizes the main change: fixing autoplay to deduplicate same-song versions, which is the core objective across all file modifications.

✏️ 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 fix/autoplay-dedup-same-song-versions

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.

@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: 2

🧹 Nitpick comments (1)
packages/bot/src/utils/music/queueManipulation.spec.ts (1)

2207-2210: Strengthen dedup assertions to exact expected outcomes.

<= 1 is too lenient and can hide regressions where expected candidates are dropped entirely. Use exact counts per scenario (e.g., 1 for the first case, 0 for the current-track duplicate case).

🔍 Suggested assertion tightening
-        expect(same_song_added).toBeLessThanOrEqual(1)
+        expect(same_song_added).toBe(1)
...
-        expect(bohemian_added).toBeLessThanOrEqual(1)
+        expect(bohemian_added).toBe(0)

Also applies to: 2253-2258

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/bot/src/utils/music/queueManipulation.spec.ts` around lines 2207 -
2210, The test uses a lenient assertion on duplicate filtering: replace the
non-specific expect(same_song_added).toBeLessThanOrEqual(1) with exact expected
counts for each scenario so failures reveal dropped candidates; for the scenario
computing same_song_added from addedTracks (variable name same_song_added, array
addedTracks) assert exactly 1 when a non-current-track duplicate should be kept,
and assert exactly 0 in the scenario where the duplicate is the current track.
Apply the same tightening to the other assertions referenced around the block
for lines 2253–2258 to use precise counts instead of <=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 `@packages/bot/src/utils/music/queueManipulation.ts`:
- Around line 614-618: The current logic sets candidateKey to getTrackKey when
normalizeTrackKey(candidate.title, candidate.author) is very short, which can
reintroduce duplicate variants; instead always base the dedupe key on
normalizeTrackKey but, when its length <= 4, append a stable fingerprint derived
from getTrackKey so short normalized keys still remain tied to the same track
(e.g., candidateKey = normalizedKey + '|' + getTrackKey(candidate) if
normalizedKey.length <= 4); update the code around normalizeTrackKey,
getTrackKey, and the candidateKey assignment to implement this deterministic
combination so deduplication still works for short titles/authors.

In `@packages/bot/src/utils/music/searchQueryCleaner.ts`:
- Line 87: The regex in searchQueryCleaner.ts currently strips any 4-digit
sequence (|\d{4}), which over-cleans numeric titles; update the pattern to
constrain year matches to a plausible range (e.g., use (?:19\d{2}|20\d{2}) or a
narrower span like (?:19[5-9]\d|20[0-4]\d) ) wherever \d{4} is used in the regex
(the leading '^(?:\d{4} +)?' group and the final alternation) so only realistic
years are matched and non-year numeric suffixes are preserved.

---

Nitpick comments:
In `@packages/bot/src/utils/music/queueManipulation.spec.ts`:
- Around line 2207-2210: The test uses a lenient assertion on duplicate
filtering: replace the non-specific
expect(same_song_added).toBeLessThanOrEqual(1) with exact expected counts for
each scenario so failures reveal dropped candidates; for the scenario computing
same_song_added from addedTracks (variable name same_song_added, array
addedTracks) assert exactly 1 when a non-current-track duplicate should be kept,
and assert exactly 0 in the scenario where the duplicate is the current track.
Apply the same tightening to the other assertions referenced around the block
for lines 2253–2258 to use precise counts instead of <=1.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 55a10b1d-092b-4086-b208-8987b90abe07

📥 Commits

Reviewing files that changed from the base of the PR and between c1af656 and 256126a.

📒 Files selected for processing (4)
  • packages/bot/src/utils/music/queueManipulation.spec.ts
  • packages/bot/src/utils/music/queueManipulation.ts
  • packages/bot/src/utils/music/searchQueryCleaner.spec.ts
  • packages/bot/src/utils/music/searchQueryCleaner.ts
📜 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: Quality Gates
  • GitHub Check: SonarCloud Scan
🔇 Additional comments (2)
packages/bot/src/utils/music/searchQueryCleaner.spec.ts (1)

239-263: Good coverage for the new hyphenated suffix handling.

These cases validate the newly added remaster/year/original variant normalization paths and help lock dedup behavior.

packages/bot/src/utils/music/queueManipulation.ts (1)

752-767: Selection-level title dedup is a solid guardrail.

This is a good second-layer filter to prevent version variants from being selected together.

Comment thread packages/bot/src/utils/music/queueManipulation.ts Outdated
Comment thread packages/bot/src/utils/music/searchQueryCleaner.ts Outdated
- use replaceAll() instead of replace() with global regex
- split HYPHENATED_VERSION_SUFFIX into array of simple regexes
  to reduce complexity from 36 to ≤20 per pattern

@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.

♻️ Duplicate comments (1)
packages/bot/src/utils/music/searchQueryCleaner.ts (1)

87-92: ⚠️ Potential issue | 🟡 Minor

Constrain year matching to plausible ranges to avoid over-cleaning.

Line 87 and Line 92 currently accept any 4 digits, so numeric non-year suffixes can be stripped as if they were versions.

Proposed fix
 const HYPHENATED_VERSION_SUFFIXES: RegExp[] = [
-    /^(?:\d{4} +)?remaster(?:ed)?(?:\s+\d{4})?$/i,
+    /^(?:(?:19|20)\d{2} +)?remaster(?:ed)?(?:\s+(?:19|20)\d{2})?$/i,
     /^official (?:audio|video|music video)$/i,
     /^(?:live|acoustic|demo|extended)$/i,
     /^(?:radio edit|album version|single version)$/i,
     /^(?:original mix|original version)$/i,
-    /^\d{4}$/,
+    /^(?:19|20)\d{2}$/,
 ]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/bot/src/utils/music/searchQueryCleaner.ts` around lines 87 - 92, The
year-matching regexes are too permissive (they use any four digits) and are
stripping non-year numeric suffixes; update both the standalone /^\d{4}$/
matcher and the optional year groups inside the remaster pattern to only accept
plausible year ranges (e.g., restrict to 1900–2099 by matching 19xx or 20xx)
instead of \d{4}; make the change in the array of cleanup regexes in
searchQueryCleaner.ts (the entries matching a standalone 4-digit token and the
optional year capture in the remaster pattern), and run/update unit tests that
cover title cleaning to ensure non-year numeric tokens are no longer removed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@packages/bot/src/utils/music/searchQueryCleaner.ts`:
- Around line 87-92: The year-matching regexes are too permissive (they use any
four digits) and are stripping non-year numeric suffixes; update both the
standalone /^\d{4}$/ matcher and the optional year groups inside the remaster
pattern to only accept plausible year ranges (e.g., restrict to 1900–2099 by
matching 19xx or 20xx) instead of \d{4}; make the change in the array of cleanup
regexes in searchQueryCleaner.ts (the entries matching a standalone 4-digit
token and the optional year capture in the remaster pattern), and run/update
unit tests that cover title cleaning to ensure non-year numeric tokens are no
longer removed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ef514144-ce2c-46ff-ab2c-3c278e1c5553

📥 Commits

Reviewing files that changed from the base of the PR and between 256126a and 57b30cc.

📒 Files selected for processing (2)
  • packages/bot/src/utils/music/queueManipulation.ts
  • packages/bot/src/utils/music/searchQueryCleaner.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/bot/src/utils/music/queueManipulation.ts
📜 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: SonarCloud Scan
  • GitHub Check: Quality Gates
🔇 Additional comments (2)
packages/bot/src/utils/music/searchQueryCleaner.ts (2)

95-97: Nice extraction of suffix classification logic.

isVersionSuffix keeps cleanTitle simpler and makes suffix behavior easier to evolve.


128-128: Good defensive integration in cleanTitle.

Line 128 correctly gates truncation on recognized version suffixes only.

- use normalizedKey !== '::' instead of length check to avoid
  bypassing dedup for short titles
- constrain year-only suffix to (19|20)xx range to avoid
  over-cleaning non-year 4-digit sequences
@LucasSantana-Dev
LucasSantana-Dev enabled auto-merge (squash) April 12, 2026 03:23
@sonarqubecloud

Copy link
Copy Markdown

@LucasSantana-Dev
LucasSantana-Dev merged commit 9573555 into main Apr 12, 2026
12 checks passed
LucasSantana-Dev added a commit that referenced this pull request May 13, 2026
* fix(bot): handle year-suffix remaster and original mix in title cleaner

* fix(bot): key autoplay candidates by normalized title, not url

* test(bot): add deduplication tests for same-song candidate selection

* fix(bot): fix sonarcloud maintainability issues in dedup code

- use replaceAll() instead of replace() with global regex
- split HYPHENATED_VERSION_SUFFIX into array of simple regexes
  to reduce complexity from 36 to ≤20 per pattern

* fix(bot): address coderabbit review issues in dedup logic

- use normalizedKey !== '::' instead of length check to avoid
  bypassing dedup for short titles
- constrain year-only suffix to (19|20)xx range to avoid
  over-cleaning non-year 4-digit sequences
@LucasSantana-Dev
LucasSantana-Dev deleted the fix/autoplay-dedup-same-song-versions branch May 23, 2026 02:21

This branch was successfully deployed

1 active deployment
Preview — d4adbc87 Deployed Apr 12, 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