Skip to content

fix(bot): pick closest-duration soundcloud fallback match - #2049

Merged
LucasSantana-Dev merged 2 commits into
mainfrom
fix/soundcloud-fallback-duration-match
Aug 20, 2026
Merged

LucasSantana-Dev merged 2 commits into
mainfrom
fix/soundcloud-fallback-duration-match

Conversation

@LucasSantana-Dev

@LucasSantana-Dev LucasSantana-Dev commented Aug 20, 2026 •

Copy link
Copy Markdown
Owner

What

Part of the investigation in #2048 ("audio not good in some moments"). findMatchingSoundCloudResult (packages/bot/src/handlers/player/soundcloudMatcher.ts) used results.find(...) — the first SoundCloud search result to pass a loose ≥75%-title-token-overlap + ±30s-duration filter. SoundCloud's search-relevance order is not a quality ranking, so a sped-up edit, "8D audio" remix, or extended mix can satisfy that threshold and get picked over the actual original — this is one of two identified contributors to the reported audio-quality complaint (the other, larger contributor was a contaminated cookies file, already fixed same day).

Fix

Filters to all qualifying candidates first, then picks the one whose duration is closest to the source track — the cheapest available signal (given SoundCloudSearchResult only carries name/url/durationInSec) that a candidate is the unaltered original rather than an altered edit.

Test plan

  • npx jest soundcloudMatcher.spec.ts — added 2 tests: closest-duration wins among multiple qualifying candidates even when ranked second by SoundCloud; falls back correctly when only one candidate has no duration data at all
  • Full bot suite: 3147 passed (2 new)
  • npm run type:check --workspace=@lucky/bot

Not in scope here

Whether to also request an explicit stream quality tier from playdl.stream()/playdl.search() — flagged as an open follow-up in #2048, needs verifying play-dl's actual default behavior first rather than guessing.


Summary by cubic

Ranks SoundCloud fallback matches by title score before duration closeness to avoid remixes/edits winning. Previously we returned the first result passing ≥75% title-token overlap and ±30s duration; now we choose among all qualifiers, prefer the higher title score, and break ties on smallest duration difference.

  • Gates unchanged (≥75% tokens; ±30s when both durations exist); ignore SoundCloud’s order; missing duration is neutral in the duration tiebreak.
  • Fallbacks: if source duration is unknown, return the first qualifying candidate; if only duration-less candidates qualify, return the first; prefer an exact-title candidate with no duration over a looser-title candidate with duration; at equal title score, prefer the duration-bearing candidate.
  • Touches packages/bot/src/handlers/player/soundcloudMatcher.ts; adds tests covering closest-duration selection, duration-less ordering, and title-priority; no API or config changes.

Written for commit e8bdb3b. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes
    • Improved SoundCloud result matching to select the qualifying result with the closest duration.
    • Preserved title-only matching when duration information is unavailable.
  • Tests
    • Added coverage for choosing the closest-duration result and handling candidates without duration data.

findMatchingSoundCloudResult took the first result in SoundCloud's own
search-relevance order to pass a loose title/duration threshold.
That order is not a quality ranking, so sped-up edits, extended
mixes, and remixes could satisfy the threshold and get played instead
of the original recording. Now filters to all qualifying candidates
and picks the closest duration match.

Found investigating a reported "audio not good in some moments"
complaint — full root-cause chain in #2048.
@github-actions

Copy link
Copy Markdown

Failed to generate code suggestions for PR

@coderabbitai

coderabbitai Bot commented Aug 20, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f7446738-9147-4a36-82a2-f088009e02fe

📥 Commits

Reviewing files that changed from the base of the PR and between 3c97291 and ee8a26c.

📒 Files selected for processing (2)
  • packages/bot/src/handlers/player/soundcloudMatcher.spec.ts
  • packages/bot/src/handlers/player/soundcloudMatcher.ts

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The SoundCloud matcher now evaluates all qualifying results and selects the closest duration when track duration is available. Tests cover closest-duration selection and fallback to a candidate without duration metadata.

Changes

SoundCloud matching

Layer / File(s) Summary
Candidate selection and validation
packages/bot/src/handlers/player/soundcloudMatcher.ts, packages/bot/src/handlers/player/soundcloudMatcher.spec.ts
The matcher filters all qualifying results, selects the closest duration when possible, and preserves first-candidate fallback behavior when track duration is unavailable. Tests cover both selection cases.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to ee8a2

The change selects the closest-duration qualifying SoundCloud result while preserving existing fallback behavior. No actionable merge-blocking risk remains after normal checks and review.

🚥 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%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: selecting the closest-duration SoundCloud fallback match.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/soundcloud-fallback-duration-match

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.

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

Graphify reviewed this change.

Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).


Graphify review — findings

Changes findMatchingSoundCloudResult to pick the duration-closest candidate rather than the first title match, filtering all qualifying results and reducing by smallest duration delta. Preserves fallback to the first candidate when no duration is available or the track duration can't be parsed. Adds spec coverage for the closest-match tie-break and the no-duration fallback.

No blocking issues surfaced.

Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 12 functions depend on the 11 functions this change touches.

Health — this change adds coupling hotspots:

  • new: createResilientStream() — 2 callers, 12 callees

Verification — 12 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 12 function(s) in the blast radius were not formally verified this run

· 1 more finding(s) on lines outside this diff (see the check run).

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 2 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/bot/src/handlers/player/soundcloudMatcher.ts Outdated
Comment thread packages/bot/src/handlers/player/soundcloudMatcher.spec.ts
The duration reduce always promoted any duration-bearing candidate
over a duration-less one, even when the duration-less candidate had
a stronger (or exact) title match. Now ranks by title-match score
first and only breaks ties on duration closeness, so an exact-title
duration-less candidate correctly beats a looser-title near-duration
match.

Covers the mixed duration-bearing/duration-less reduce branches that
the prior tests never exercised.
@github-actions github-actions Bot added size/m and removed size/s labels Aug 20, 2026

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

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 1 advisory finding(s) below merit a look before merge.


Graphify review — findings

Replaces the first-match selection in findMatchingSoundCloudResult with a scored candidate reduction that ranks by title-match score first, then by duration closeness as a tiebreaker, treating missing duration data as neutral. Adds spec coverage for the new preference ordering (closest duration among multiple candidates, exact title over looser duration matches, and duration-less fallbacks).

Worth a look

  • Result ordering contract changed when duration is supplied — packages/bot/src/handlers/player/soundcloudMatcher.ts:97 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 12 functions depend on the 11 functions this change touches.

Health — this change adds coupling hotspots:

  • new: createResilientStream() — 2 callers, 12 callees

Verification — 12 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 12 function(s) in the blast radius were not formally verified this run

· 1 more finding(s) on lines outside this diff (see the check run).

@sonarqubecloud

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai 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.

0 issues found across 2 files (changes from recent commits).

Requires human review: AI evaluation unavailable; defaulting to comment-only for safety.

Re-trigger cubic

@LucasSantana-Dev
LucasSantana-Dev merged commit 738efb8 into main Aug 20, 2026
50 checks passed
@LucasSantana-Dev
LucasSantana-Dev deleted the fix/soundcloud-fallback-duration-match branch August 20, 2026 23:20
LucasSantana-Dev added a commit that referenced this pull request Aug 22, 2026
🤖 I have created a release *beep* *boop*
---


<details><summary>2.39.6</summary>

##
[2.39.6](v2.39.5...v2.39.6)
(2026-08-22)


### Bug Fixes

* **bot:** drop the audio-features scoring path, spotify returns 403
([#2074](#2074))
([11891bf](11891bf))
* **bot:** drop the autoplay arm that calls a removed spotify endpoint
([#2071](#2071))
([682a795](682a795))
* **bot:** fall back past a dead spotify arm in /artist
([#2052](#2052))
([45dc998](45dc998))
* **bot:** make three silent /play failures observable
([#2062](#2062))
([e6b2810](e6b2810))
* **bot:** pick closest-duration soundcloud fallback match
([#2049](#2049))
([738efb8](738efb8))
* **bot:** report a dead autoplay replenish at error level
([#2063](#2063))
([2c5962e](2c5962e))
* **bot:** report spotify extractor health instead of failing silently
([#2060](#2060))
([ddaa287](ddaa287))
* **bot:** rerank search results toward exact artist/title match
([#2045](#2045))
([0c719d5](0c719d5))
* **bot:** resolve /album text queries to an album url
([#2053](#2053))
([4498299](4498299))
* **bot:** restore youtube-dl-exec, discord-player-youtubei needs it
undeclared
([#2040](#2040))
([c75475b](c75475b))
* **bot:** stop reporting an outage when the fallbacks found nothing
([#2069](#2069))
([37412e2](37412e2))
* **bot:** surface dead last.fm env session key to sentry
([#2047](#2047))
([3c97291](3c97291))
* **bot:** update a case reason through the service layer
([#2066](#2066))
([187d783](187d783))
* **bot:** use metadata setter instead of direct property assignment
([#2042](#2042))
([740d53e](740d53e))


### Performance Improvements

* **bot:** cut yt-dlp timeout from 15s to 6s
([#2044](#2044))
([39e9e3c](39e9e3c))
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
This was referenced Oct 1, 2026
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