Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions packages/bot/src/utils/music/queueManipulation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3321,6 +3321,88 @@ describe('queueManipulation — multi-user VC blend', () => {
expect(addTrackMock).not.toHaveBeenCalled()
})

it.each([
'Relaxing Rain Sounds for Sleep',
'Ocean Waves Sounds 1 Hour',
'White Noise for Baby Sleep',
'ASMR Soft Spoken Triggers',
'Binaural Beats Deep Focus',
'Guided Meditation Music 432Hz',
'Spa Music Relaxation',
])('rejects ambient/noise track "%s"', async (title) => {
const addTrackMock = jest.fn()
const queue = createQueueMock({
currentTrack: {
url: 'https://example.com/current',
title: 'Current Song',
author: 'Current Artist',
id: 'curr',
durationMS: 200000,
requestedBy: { id: 'user-1' },
} as unknown as Track,
player: {
search: jest.fn().mockResolvedValue({
tracks: [
{
url: 'https://example.com/ambient',
title,
author: 'Ambient Channel',
id: 'amb1',
durationMS: 3600000,
requestedBy: null,
},
],
}),
},
addTrack: addTrackMock,
metadata: { requestedBy: { id: 'user-1' } },
})

await replenishQueue(queue as unknown as GuildQueue)

expect(addTrackMock).not.toHaveBeenCalled()
})
Comment on lines +3324 to +3364

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Make these new rejection tests independent of duration filters.

Line [3351] and Line [3391] use 1-hour candidates, which are already excluded by existing duration caps before title regex checks run. These tests can pass even if the new ambient/EDM guards are removed.

Proposed test fix
-                            durationMS: 3600000,
+                            durationMS: 240000,
...
-                            durationMS: 3600000,
+                            durationMS: 240000,

Also applies to: 3366-3404

🤖 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 3324 -
3364, The rejection tests currently use 1-hour tracks which are already filtered
by duration caps, so update the test cases in the spec that call replenishQueue
(the it.each blocks using createQueueMock and addTrackMock) to use durations
inside the allowed range (e.g., set durationMS to a short valid value like
200000) for the candidate ambient/EDM tracks so the tests exercise title-based
rejection logic instead of duration filters; ensure you only change the
candidate track's durationMS (leave title, id and player.search shape, and the
use of addTrackMock/replenishQueue intact) so the new ambient/EDM guards are
actually validated.


it.each([
'DJ Set Live at Tomorrowland 2024',
'Festival Set Main Stage',
'2 Hour EDM Mix 2024',
'Extended Mix Club Night',
'Trance Mix Progressive',
])('rejects EDM mix/set track "%s"', async (title) => {
const addTrackMock = jest.fn()
const queue = createQueueMock({
currentTrack: {
url: 'https://example.com/current',
title: 'Current Song',
author: 'Current Artist',
id: 'curr',
durationMS: 200000,
requestedBy: { id: 'user-1' },
} as unknown as Track,
player: {
search: jest.fn().mockResolvedValue({
tracks: [
{
url: 'https://example.com/edm',
title,
author: 'DJ Channel',
id: 'edm1',
durationMS: 3600000,
requestedBy: null,
},
],
}),
},
addTrack: addTrackMock,
metadata: { requestedBy: { id: 'user-1' } },
})

await replenishQueue(queue as unknown as GuildQueue)

expect(addTrackMock).not.toHaveBeenCalled()
})

it('penalizes low-quality uploads with noise indicators in title', async () => {
const addTrackMock = jest.fn()
const queue = createQueueMock({
Expand Down
14 changes: 14 additions & 0 deletions packages/bot/src/utils/music/queueManipulation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1745,6 +1745,12 @@ function getTrackKey(track: Track): string {

const FUZZY_TITLE_THRESHOLD = 0.82

const AMBIENT_NOISE_RE =
/\b(?:rain sounds?|rain for sleep|ocean waves?|waves? sounds?|nature sounds?|forest sounds?|thunder sounds?|white noise|brown noise|pink noise|asmr|sleep sounds?|sleep music|relaxing rain|ambient sounds?|binaural beats?|solfeggio|healing frequ|528 ?hz|432 ?hz|963 ?hz|chakra healing|spa music|massage music|yoga music|deep sleep|baby sleep|guided meditation|meditation music)\b/i // NOSONAR S5852 — trusted track title from internal API, not user input

const EDM_MIX_RE =
/\b(?:dj set|festival set|\d+ ?(?:hour|hr) mix|extended mix|club mix|nightclub mix|edm mix|trance mix)\b/i // NOSONAR S5852 — trusted track title from internal API, not user input

Comment on lines +1748 to +1753

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Regex currently misses common blocked-title variants.

Line [1749] uses frequ?e?n?c?, which won’t reliably match “frequency/frequencies”. Also, Line [1818] tests raw titles, so common forms like EDM-mix / white-noise can bypass the filter.

Proposed fix
-const AMBIENT_NOISE_RE =
-    /\b(?:rain\s{0,3}sounds?|rain\s{0,3}for\s{0,3}sleep|ocean\s{0,3}waves?|waves?\s{0,3}sounds?|nature\s{0,3}sounds?|forest\s{0,3}sounds?|thunder\s{0,3}sounds?|white\s{0,3}noise|brown\s{0,3}noise|pink\s{0,3}noise|asmr|sleep\s{0,3}sounds?|sleep\s{0,3}music|relaxing\s{0,3}rain|ambient\s{0,3}sounds?|binaural\s{0,3}beats?|solfeggio|healing\s{0,3}frequ?e?n?c?|528\s?hz|432\s?hz|963\s?hz|chakra\s{0,3}healing|spa\s{0,3}music|massage\s{0,3}music|yoga\s{0,3}music|deep\s{0,3}sleep|baby\s{0,3}sleep|guided\s{0,3}meditation|meditation\s{0,3}music)\b/i
+const AMBIENT_NOISE_RE =
+    /\b(?:rain\s{0,3}sounds?|rain\s{0,3}for\s{0,3}sleep|ocean\s{0,3}waves?|waves?\s{0,3}sounds?|nature\s{0,3}sounds?|forest\s{0,3}sounds?|thunder\s{0,3}sounds?|white\s{0,3}noise|brown\s{0,3}noise|pink\s{0,3}noise|asmr|sleep\s{0,3}sounds?|sleep\s{0,3}music|relaxing\s{0,3}rain|ambient\s{0,3}sounds?|binaural\s{0,3}beats?|solfeggio|healing\s{0,3}frequenc(?:y|ies)|528\s?hz|432\s?hz|963\s?hz|chakra\s{0,3}healing|spa\s{0,3}music|massage\s{0,3}music|yoga\s{0,3}music|deep\s{0,3}sleep|baby\s{0,3}sleep|guided\s{0,3}meditation|meditation\s{0,3}music)\b/i

-    const candidateTitle = candidate.title ?? ''
+    const candidateTitle = (candidate.title ?? '').replace(/[-_/]+/g, ' ')

Also applies to: 1818-1824

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

In `@packages/bot/src/utils/music/queueManipulation.ts` around lines 1748 - 1753,
AMBIENT_NOISE_RE and EDM_MIX_RE miss variants like “frequency/frequencies” and
titles with hyphens/underscores (e.g., white-noise, EDM-mix); update
AMBIENT_NOISE_RE to use a correct token for frequency such as
"frequen(?:cy|cies)" instead of "frequ?e?n?c?" and change the inter-word
separator tokens from "\s{0,3}" to a character class that allows spaces, hyphens
and underscores like "[\s-_]{0,3}", then apply the same separator change to
EDM_MIX_RE (and the similar regex block referenced at lines ~1818-1824) so
dashed/underscored variants are matched.

function isDuplicateCandidate(
track: Track,
excludedUrls: Set<string>,
Expand Down Expand Up @@ -1809,6 +1815,14 @@ function calculateRecommendationScore(
return { score: -Infinity, reason: 'track too long' }
}

const candidateTitle = candidate.title ?? ''
if (AMBIENT_NOISE_RE.test(candidateTitle)) {
return { score: -Infinity, reason: 'ambient/noise content' }
}
if (EDM_MIX_RE.test(candidateTitle)) {
return { score: -Infinity, reason: 'dj mix / edm set' }
}

let score = 1
const reasons: string[] = []

Expand Down