58 Commits
Author SHA1 Message Date
HoneyandClaude Sonnet 4.6 941a486913 fix: strip only Unicode symbols from artist name for ytsearch queries
Using the full artist name with Unicode symbols (e.g. ☆NoAki☆) in ytsearch
caused YouTube to return 0-1 completely irrelevant results, letting wrong songs
fall through to the no-filter fallback. Strip only \p{S} (Unicode symbol chars
like ☆ ★ ♥) but keep ASCII punctuation — so N!GHT stays "N!GHT" (important for
disambiguation) while ☆NoAki☆ becomes "NoAki" (searchable).
YTM URL still uses the original artist name with all chars intact.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 12:42:06 +02:00
HoneyandClaude Sonnet 4.6 e858b02df7 fix: use original artist name in YTM search and add strict channel filter
Use mainArtist (with special chars) for ytsearch queries so e.g. "N!GHT - Yume"
searches correctly instead of "NGHT - Yume" which YouTube misreads as "night"
and returns ambience videos.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 11:50:19 +02:00
HoneyandClaude Sonnet 4.6 03fb45b986 fix: use original artist name in YTM search and add strict channel filter
- YTM URL now uses unstripped artist name (e.g. "N!GHT" instead of "NGHT") for
  better search ranking on YouTube Music
- Steps 1-2 of cascade now include a soft channel ~= filter using the artist's
  first word, preventing wrong-artist songs with matching titles from being
  downloaded (e.g. a different "Moonlight" for N!GHT)
- Steps 3+ drop the channel filter so label-hosted tracks still get found

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 02:25:28 +02:00
HoneyandClaude Sonnet 4.6 8f8c38fcf0 fix: word-boundary variant filter; reattempt ALTCHA verify payload structure
- ytdlp.js: use \b word boundaries in all variant filter regexes so that
  partial matches like "nightcoreals" containing "nightcore" no longer
  falsely reject official videos; also fixes sped regression (!~= \bsped\b
  instead of the too-narrow "sped up" pattern)
- squid.js: restructure verify payload to mirror challenge response layout
  { parameters, solution: { number, derivedKey }, signature }

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 01:48:29 +02:00
HoneyandClaude Sonnet 4.6 b9692e6f08 fix: include ALTCHA signature in verify payload; case-insensitive variant filter
- squid.js: add top-level signature from challenge response to verify payload
  (server added signature validation, causing HTTP 400 without it)
- ytdlp.js: switch variant filter from !*= to !~= (?i) so Remix/REMIX/remix
  are all rejected, not just lowercase

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 01:27:10 +02:00
HoneyandClaude Sonnet 4.6 598c108214 fix: detect YTM artist channel expansion in getYtmVideoUrls; revert PWA MediaSession changes
- ytdlp.js: watch for [youtube:tab] in yt-dlp output during flat-playlist step;
  return [] when channel expansion is detected so cascade falls through to ytsearch
- Revert player.js / main.js / state.js PWA _changingTrack changes (not effective)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-03 01:11:36 +02:00
HoneyandClaude Sonnet 4.6 7aad4989f3 fix: pre-filter YTM search results to skip artist channel expansion
--match-filter 'webpage_url !*= /browse/' was applied to individual videos
AFTER yt-dlp expanded an artist channel into its uploads playlist — by then
each video had a /watch?v= URL, so the filter never fired.

New approach: run yt-dlp --flat-playlist --print webpage_url first to get
the raw search result URLs, filter /browse/ entries in Node.js, then pass
only the actual watch?v= video URLs to yt-dlp for download with --max-downloads 1.
The channel is never expanded; we get the real song from the search results.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 20:51:21 +02:00
HoneyandClaude Sonnet 4.6 ac8d26bf9d feat: split backend into lib/ modules + add squid.wtf (Qobuz) download backend
- backend/lib/config.js  — CONFIG from env (adds DOWNLOAD_BACKEND, SQUID_QUALITY)
- backend/lib/jobs.js    — jobs Map, updateJob(), log()
- backend/lib/metadata.js — iTunes, artwork, lyrics, sanitize helpers
- backend/lib/ytdlp.js   — yt-dlp download cascade + shared embedMetadata()
- backend/lib/squid.js   — ALTCHA PoW solver, Qobuz search/download via squid.wtf
- backend/lib/downloader.js — backend selector: ytdlp | squid | auto (squid-first + fallback)
- novasonic-server.js thinned to Express routes only, imports from lib/
- docker-compose: mount full backend/ dir, install deps outside read-only volume
- .env.example: document DOWNLOAD_BACKEND and SQUID_QUALITY

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 20:44:26 +02:00