Skip to content

feat(songs): add SoundCloud as a song source - #2

Merged
Nxssie merged 2 commits into
mainfrom
feature/soundcloud
Jun 30, 2026
Merged

Nxssie merged 2 commits into
mainfrom
feature/soundcloud

Conversation

@Nxssie

@Nxssie Nxssie commented Jun 30, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds SoundCloud as a song source, both by pasted URL (auto-detected from the host) and by
    search (YT/SC toggle). The backend resolves, searches, and streams SoundCloud via yt-dlp
    the same way it already does YouTube — no new dependencies.
  • Supports single tracks, YouTube playlists, and SoundCloud sets through one resolver
    shared between the HTTP add-song endpoint and the Discord /play command.
  • Replaces the embedded YouTube preview player with artwork + an "open in…" link, dropping
    the react-youtube dependency.
  • Includes a sync fix: the skip endpoint and the "now playing" panel both used "the
    highest-voted unplayed song" as a stand-in for "what's actually streaming," which diverges
    as soon as a pending song's votes overtake the one currently playing (it stays
    played=false until it finishes). That let a single skip mark two songs as played.
    Both are now anchored to the real songId tracked in currentTracks.
  • Guards against double-submit on the add-song form.

Test plan

  • bun test in packages/server (23/23)
  • bun run build in packages/server and packages/web
  • Verified live against real yt-dlp: YT/SC search, adding a track by URL on both
    sources, invalid-URL rejection, a SoundCloud set (11 tracks, deferred titles resolved), a
    YouTube playlist (100 tracks, regression)
  • Test /play <soundcloud url> on Discord with the bot connected to a voice channel
  • Verify in the UI: YT/SC search toggle, artwork + link preview, and that the
    now-playing panel / skip button stay in sync when a queued song's votes overtake the one
    currently playing

Nxssie added 2 commits June 30, 2026 22:20
- detect source from pasted URL host (lib/sources.ts), search via
  scsearch/ytsearch with a source toggle, and add single tracks,
  YouTube playlists, and SoundCloud sets through one shared resolver
- store source + thumbnail on songs (SoundCloud has no derivable
  thumbnail CDN pattern like YouTube's i.ytimg.com)
- drop the embedded YouTube preview player for artwork + an
  open-in-source link, removing the react-youtube dependency
- extend the Discord /play command to accept SoundCloud URLs too
- guard double-submit on the add-song form
The skip endpoint and the songs poll both picked "current" as the
highest-voted unplayed song. While a song plays it stays played=false
in the DB, so once a pending song's votes overtake it mid-playback,
both picked the wrong song: the vote-skip would 404/403 against votes
that don't belong to what's on air, mark that wrong song played (never
having streamed a second of it), and the real track would also get
marked played when the player stopped — skipping two songs per click.

Thread currentTracks' songId through as currentSongId so the skip
route and the frontend's "now playing" both anchor to what's actually
streaming, falling back to vote order only when nothing is (bot not
connected).
@Nxssie
Nxssie merged commit a4aff6b into main Jun 30, 2026
2 checks passed
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.

1 participant