Commit Graph
60 Commits
Author SHA1 Message Date
HoneyandClaude Opus 4.8 e93c0c7ab1 fix(backend): drop YTM Songs filter param — it dropped the exact track
The &params= Songs-tab filter re-ranked YTM results toward a same-named
artist's discography and excluded the official track (qNffDItRUeo) entirely,
even logged-out. The default blended search (what the browser shows) ranks
the exact track first. Removing the param so yt-dlp gets the same result set.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 11:15:12 +02:00
HoneyandClaude Opus 4.8 c4e4c8c090 fix(backend): use space (not dash) between artist and title in search query
"MINA - recognize" skewed YTM ranking toward a same-named artist's full
discography, so the actual track (qNffDItRUeo) never appeared in results.
"MINA recognize" — matching how users type in the YTM search box — ranks
the exact official track first.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 11:06:00 +02:00
HoneyandClaude Opus 4.8 c34123af38 fix(backend): apply web_music client to YTM search extraction too
The YTM search (getYtmVideoUrls) ran without the web_music client, so yt-dlp
parsed the search page as a generic YouTube search and returned unrelated
videos instead of the native Songs shelf — the actual artist track (e.g.
qNffDItRUeo for MINA - recognize) never appeared in results. Apply the same
player_client=web_music,default arg to the search step.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 10:48:26 +02:00
HoneyandClaude Opus 4.8 9014659112 fix(backend): use web_music player client for YTM track access
yt-dlp's android_vr player client returns "This video is not available" for
many YouTube Music Art Track / topic uploads (e.g. MINA - recognize) that
play fine in the browser. Switch to player_client=web_music with default
fallback so these tracks become downloadable, fixing the cascade falling
through to wrong YouTube videos.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 10:46:53 +02:00
HoneyandClaude Sonnet 4.6 ce4577e8f4 fix(backend): strip release suffix from title metadata tag
searchTitle (e.g. "recognize") is now passed to embedMetadata instead of
the raw title ("recognize - Single"), so the ID3 title tag matches the
actual song name. Album tag stays unchanged ("recognize - Single").

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 10:44:13 +02:00
HoneyandClaude Sonnet 4.6 bb0be52f46 fix(backend): fix getYtmVideoUrls always returning empty + remove unsupported ytmsearch5
[youtube:tab] in stderr fires for all YTM search page processing, not just
artist channel expansion, causing channelExpanded=true for every search and
returning [] — bypassing all YTM cascade steps entirely. Fix: only check
stdout for /browse/UC (actual channel URL in results). Remove ytmsearch5:
scheme which is not supported by this yt-dlp version. Revert pool to 10.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 10:32:22 +02:00
HoneyandClaude Sonnet 4.6 3c54850cca fix(backend): add ytmsearch5 step + expand YTM pool to 20 for better coverage
ytmsearch5 (yt-dlp native YTM search) added as step 2 — returns different
result ordering than the manual YTM URL, recovering songs that the URL
approach ranks too low. YTM pool expanded from 10 → 20 results to reduce
fallthrough to YouTube.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 10:25:37 +02:00
HoneyandClaude Sonnet 4.6 4804023a98 fix(backend): don't abort cascade on yt-dlp non-zero exit (e.g. video not available)
spawnYtdlp now always resolves so the hasAudio() cascade continues when a
single YTM result is geo-blocked or unavailable. Error is still logged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 10:23:59 +02:00
HoneyandClaude Sonnet 4.6 88d3e336c8 fix(backend): use searchTitle in YTM URL (was using raw title with release suffix)
YTM search used `title` directly, so "recognize - Single" was searched on
YouTube Music instead of "recognize" — causing no YTM results and falling
through to the less reliable YouTube search cascade.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 10:19:43 +02:00
HoneyandClaude Sonnet 4.6 d5bc887f31 fix(backend): tighten duration filter margin from ±15% to ±10% (min 10s)
Matches spotdl behaviour; still covers YouTube intros/outros while
reducing false positives from similarly-lengthed wrong songs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 10:07:19 +02:00
HoneyandClaude Sonnet 4.6 5f257bf451 fix(backend): generalize release-suffix stripping from search title
Handles all Spotify trailing suffixes: Single, EP, Remaster, Deluxe Edition,
Bonus Tracks, B-Sides, bare years (2024), Official Music Single, etc.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 09:44:06 +02:00
HoneyandClaude Sonnet 4.6 bff652a415 fix(backend): strip release-type suffixes from YTM search title + extend stopwords
- "recognize - Single" title → search uses "recognize" (strips "- Single/EP/Album/…")
- Adds Single/EP/Remaster/Deluxe/… to titleKws STOPWORDS so they never become
  mandatory title-match filters (no YouTube video title contains "Single")

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 09:42:07 +02:00
HoneyandClaude Sonnet 4.6 ecb7721e3b fix(backend): only append album to YTM query for Japanese titles
Western tracks now use artist + title only (matches spotdl behaviour).
Album suffix was causing noise for short English titles like singles
where album name = title + "Single".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 09:35:32 +02:00
HoneyandClaude Sonnet 4.6 319a3804f3 fix(backend): strip title-duplicate and generic words from album search suffix
Album "recognize - Single" produced query "MINA - recognize recognize Single"
because "recognize" appeared in both title and album name. Now filters album
words already present in the title, plus generic words (Single, EP, Remaster…).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 09:29:39 +02:00
HoneyandClaude Sonnet 4.6 f1bdd811ca chore: remove squid.wtf (Qobuz) backend — yt-dlp only
Deletes backend/lib/squid.js; strips all references from downloader.js,
config.js, novasonic-server.js, docker-compose.yml, .env.example, README,
and CHANGELOG. Default DOWNLOAD_BACKEND is now ytdlp.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 20:59:30 +02:00
HoneyandClaude Sonnet 4.6 adcbb2e883 feat: replace Bandsintown with Ticketmaster for concert events
Backend: swap /api/events/:artist to use Ticketmaster Discovery API
(startDateTime=now, classificationName=music, size=20, sort by date).
Maps TM response to the same {datetime, venue, offers} shape the modal
expects. Returns [] if TICKETMASTER_API_KEY is not set.

Frontend: remove all debug console.logs from events.js; drop redundant
client-side date filter (TM already filters by startDateTime server-side).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 20:51:51 +02:00
HoneyandClaude Sonnet 4.6 36a0b38eca feat: server-side romaji overrides (shared list); preload ExoPlayer from SharedPreferences on cold start
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-05 10:47:25 +02:00
HoneyandClaude Sonnet 4.6 63ff8920bf fix: repair Japanese song download pipeline
Five separate root causes fixed:

1. buildTitleKeywords (ytdlp.js): For Japanese titles \w strips all
   kana/kanji leaving no keywords. Now uses the first whitespace-
   delimited segment as a literal regex keyword so --match-filter
   title ~= requires the YTM video to contain the Japanese text.

2. Tokenizer wait (ytdlp.js): If kuromoji hasn't finished loading when
   a Japanese download starts, romajiForStorage returns the original
   Japanese text unchanged — producing Japanese folder/filenames and
   skipping sort tags. Now waits up to 30 s for the tokenizer.

3. titleOnlyMatch guard (metadata.js): iTunes titleOnlyMatch (no artist
   check) was used as a fallback for all searches. For Japanese
   titles/artists this matched wrong US songs with identical titles
   (common in anime OSTs). Now titleOnlyMatch is skipped when the
   search title or artist contains Japanese characters.

4. squid.js rawArtist: rawArtist was not in squid's signature and
   never forwarded to embedMetadata, so Qobuz-downloaded J-Pop tracks
   stored the iTunes-resolved English name as artist instead of the
   Japanese original. Fixed by accepting and forwarding rawArtist.

5. squid.js romaji paths: Folder and filename used raw artist/title
   with no romaji conversion, creating Japanese-named paths
   inconsistent with the yt-dlp path. Now uses romajiForStorage same
   as ytdlp.js.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 01:40:46 +02:00
HoneyandClaude Sonnet 4.6 2df5a54985 fix: prevent 9-second downloads caused by short iTunes duration match
When iTunes enrichment returns a jingle/preview as the first result (e.g.
trackTimeMillis=9000), the yt-dlp duration filter becomes impossible
(duration > 30 & duration < 24), all filtered steps fail, and the final
unfiltered fallback downloads whatever YouTube returns first — often a
short clip.

Fix 1: spotify.js — only copy iTunes trackTimeMillis to durationMs when
it is > 30 seconds (genuine song, not a jingle or preview).

Fix 2: ytdlp.js — only enter the duration-filtered search branch when
durationMs > 30 000ms, so a corrupted short value silently falls back to
the unfiltered search path which still finds the correct full song.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 00:06:33 +02:00
HoneyandClaude Sonnet 4.6 78024181f0 fix: always write English genre for all download paths
1. JP genre mapping table in metadata.js — when only JP iTunes has the song
   (niche Japanese artists), map localized JP genre names (アニメ, ポップ, etc.)
   to English equivalents so files never get Japanese characters in genre tag.

2. Spotify playlist import (alreadyEnriched path) — was skipping iTunes lookup
   entirely, leaving genre empty. Now does a lightweight genre-only lookup.

3. Single track download with Spotify album — was skipping iTunes when album
   already known from Spotify. Now also fetches genre from iTunes when missing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 22:58:08 +02:00
HoneyandClaude Sonnet 4.6 760d8d5e1f fix: use US iTunes genre to avoid Japanese-localized genre names
JP store returns localized genres (e.g. イージーリスニング instead of Easy Listening).
Fetch JP and US in parallel, use JP match for title/album/artwork but always
take genre from US result so genre is always in English/Western characters.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 19:14:43 +02:00
HoneyandClaude Sonnet 4.6 67f4be272a fix: ie-totaltracks element id + JP-strict/US-fallback iTunes matching
Prevent false Japanese matches by never using JP title-only fallback.
Strategy: JP strict → US strict → US title-only so niche Western tracks
still resolve but same-English-title Japanese songs don't pollute results.

Also fix JS error in autofillItunes: ie-total → ie-totaltracks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 18:15:04 +02:00
Honey 09cec18b33 fix: strip punctuation in normalizeTitle so comma variants match (e.g. 'Mr. Lawrence' vs 'Mr, Lawrence') 2026-05-27 17:49:31 +02:00
Honey 9821334cc8 fix: split multi-artist string before iTunes search query in lookupItunesTrackMeta 2026-05-27 17:40:14 +02:00
Honey 3837783225 fix: iTunes JP-first with US fallback; romaji filter in playlist/starred search 2026-05-27 17:16:57 +02:00
Honey a9463917e3 fix: use iTunes country=jp globally — returns Japanese original names, identical for non-Japanese music 2026-05-27 15:21:11 +02:00
HoneyandClaude Sonnet 4.6 212491aa89 fix: convert katakana proper nouns (e.g. ヨルシカ) to romaji in sort tags
When kuromoji marks a katakana token as reading '*' (unknown word — common
for band names like ヨルシカ), the code fell back to the surface_form which
is still katakana. _hiraToRomaji can't handle katakana so it passed through
unchanged, causing sort tags to show ヨルシカ instead of Yorushika.

Fix: if the surface_form contains katakana and reading is *, convert it
mechanically via _kataToHira + _hiraToRomaji — katakana-to-romaji is always
unambiguous and needs no dictionary.

Also add a Japanese-char guard in the frontend when applying romaji index
values, so stale cache entries can never overwrite correct values with Japanese.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-27 02:52:35 +02:00
HoneyandClaude Sonnet 4.6 40efa207bb fix: move albumQuerySuffix before ytmQuery to resolve temporal dead zone crash
albumQuerySuffix and related consts (escRe, JP_CHARS, variantFilter, titleKws,
artistChannelPart) were declared after the ytmQuery/query lines that reference them,
causing ReferenceError on every download. Moves the block to before its first use.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 18:20:15 +02:00
HoneyandClaude Sonnet 4.6 1812500523 fix: YTM search for Japanese tracks - channel filter + album query context
- Skip channel filter when artistFirstWord is non-ASCII (Japanese kanji/kana):
  YouTube channels are named in romaji/English, not kanji — the filter was
  rejecting all valid results and causing 6+ extra cascade steps
- Add albumQuerySuffix: when title is Japanese (no keyword match) OR has only
  one romaji keyword, include the album's first two English words in the search
  query so YTM ranks the official OST/album version above fan covers

Fixes: 照井順政 channel filter rejecting all YTM results
Fixes: "Souiunatsu" matching covers with romaji subtitle instead of official OST

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 16:12:27 +02:00
HoneyandClaude Sonnet 4.6 1aff19e319 feat: keep Japanese in main tags, romaji in sort tags + frontend toggle
- Downloads now store original Japanese in TITLE/ARTIST/ALBUM tags
  so Apple Music, iTunes, YTM etc. all see the authentic original text
- Sort tags (TITLESORT/ARTISTSORT/ALBUMSORT) written with romaji for
  apps that use them for sorting/display
- iTunes-resolved English artist name used for ARTISTSORT and folder names
  when available (more accurate than kuromoji for known artists)
- rawArtist parameter added to downloadTrack so YTM search query uses
  the original Japanese channel name (fixes wrong song downloads)
- spotify.js: artistName preserved as original; itunesArtistName stored
  separately so the Spotify importer shows Japanese titles
- romaji index now includes titleRomaji/artistRomaji/albumRomaji fields
- Frontend: showRomaji setting (Settings > Bibliothek) — when on, player
  bar, now-playing, queue, and song lists all show romaji via index lookup
- refreshDisplayMode() updates all live UI when the toggle is saved

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 14:58:53 +02:00
HoneyandClaude Sonnet 4.6 f1eabf7099 fix: playlist matching for romaji-stored Japanese tracks + punctuation cleanup
- Clean Japanese punctuation (、。・) in romajiForStorage so it doesn't pass through
- Add POST /api/romaji-convert endpoint for batch title conversion
- Add romajiConvert() to api.js
- Add third fallback in _createNdPlaylist: convert Japanese title to romaji and
  search Navidrome with it (for songs already downloaded with romaji tags)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 01:20:37 +02:00
HoneyandClaude Sonnet 4.6 c7bebd5691 fix: correct artist names and prevent wrong song downloads for Japanese tracks
- spotify.js: stop overwriting trackName with iTunes English title —
  yt-dlp must search with original Japanese title to find the right song
  (was downloading English covers e.g. Ghost In A Flower instead of 幽霊花)
- metadata.js: add title-only fallback in lookupItunesTrackMeta so tracks
  are found even when kuromoji gives wrong artist romanization (e.g.
  Terui Jun Sei vs iTunes Yoshimasa Terui); also return itunesArtistName
- novasonic-server.js: use itunesArtistName from iTunes lookup as the
  stored artist when available (single-track and playlist download paths)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 00:39:26 +02:00
HoneyandClaude Sonnet 4.6 392da7e021 fix: romaji for album names + Japanese playlist track matching
- ytdlp.js + novasonic-server.js: apply romajiForStorage to album tag
  and folder/rename paths (was only applied to artist/title before)
- ui.js: _createNdPlaylist falls back to romaji index for Japanese titles
  since Navidrome search3 doesn't index Japanese text properly

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 00:36:16 +02:00
HoneyandClaude Sonnet 4.6 446c583f7f feat: normalize Japanese artist/title names to romaji at storage time
- Add romajiForStorage() to romaji.js — smart word spacing + Title Case
- ytdlp.js: apply to folder names, filenames, and embedded tags
- novasonic-server.js: apply in edit-metadata endpoint and Spotify resolve
- spotify.js: update track artist/name from iTunes canonical English names

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 20:22:22 +02:00
HoneyandClaude Sonnet 4.6 f03c6dfabd fix: remove space and / as artist separators, keep &
Separators: • · ; , & — space and / removed to avoid breaking multi-word artist names.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 12:31:52 +02:00
HoneyandClaude Sonnet 4.6 e5bb2bf2d3 feat: accept space, &, / as artist separators in metadata editor
- Space as fallback separator on save when no explicit separator present
  (Artist1 Artist2 → Artist1;Artist2)
- & and / added to explicit separator set everywhere
- navidromeArtist (download path) also handles /

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 12:30:18 +02:00
HoneyandClaude Sonnet 4.6 0823c1ca86 fix: split on & when deriving artist folder name
"Arriez & King Dif" was used as-is for the folder; now splits on , ; &
so only the first artist is used: "Arriez".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 23:45:40 +02:00
HoneyandClaude Sonnet 4.6 4842c89c4e feat: artist separator normalization + separator hints in metadata editor
- Normalize •, ·, ;, , separators on save (both edit and download paths)
- Fix ndSong scope bug (was inaccessible outside try block in edit-metadata)
- Apply _normalizeArtists to artist/albumArtist before ffmpeg tags and file rename
- Storage format: Artist A;Artist B (no space, Navidrome/MusicBrainz style)
- Display format: Artist A; Artist B (space, via _fmtArtists in frontend)
- Show separator hint below label in metadata editor fields
- Remove hover effect on player bar song title

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 22:43:51 +02:00
HoneyandClaude Sonnet 4.6 7ba5b8ce9a feat: artist in filename, hide album=title subtitle, remove title hover
Naming convention (download + edit-metadata):
  Before: {01 - }Title.ext
  After:  {01 - }Artist1, Artist2 - Title.ext
- ytdlp.js: builds fileBase with artist prefix; findExistingTrack checks
  both new and old format so existing files aren't re-downloaded
- metadata.js: findExistingTrack accepts optional safeArtist param
- novasonic-server.js: file rename on title edit now includes artist
  (falls back to Navidrome's stored artist if not provided in body)

Song list subtitle: hide album name when album === title (singles where
the album is named after the track appear to duplicate the title)

Player bar: removed .player-title:hover underline/colour effect

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 22:33:35 +02:00
HoneyandClaude Sonnet 4.6 17414ca888 fix: iTunes artist match and MusicBrainz first-artist-only query
iTunes: split artist by [\s,;/] not just space so "VXLLAIN, iGRES"
yields first word "vxllain" (no trailing comma) and matches correctly.

MusicBrainz: extract first artist from the full credit string (split on
,;&•) and use `artistname` field — MB stores credits like "VXLLAIN feat.
iGRES & ENXK" which never matched the comma-joined full string.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 22:00:58 +02:00
HoneyandClaude Sonnet 4.6 e05daf3824 remove: lyrics downloading (fetchLyrics, .lrc files, uslt tag embedding)
Removes LRCLIB lookup, .lrc sidecar file writing, and lyrics/uslt
metadata embedding from all downloads.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 21:34:59 +02:00
HoneyandClaude Sonnet 4.6 d785a4c09a fix: SC metadata fields, albumartist & separator, importer clear, folder rename on album edit
- SC tracks: use artworkUrl/album/genre fields (not iTunes artworkUrl100/collectionName/primaryGenreName)
- Playlist handler: same SC field fallbacks for artwork, album, genre, year
- ytdlp.js: convert & to , in album_artist tag so Navidrome albumartist.Split works
- Importer: clear both previews on any URL input change, not just on clear
- edit-metadata: rename album folder on disk when album name changes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 21:19:42 +02:00
HoneyandClaude Sonnet 4.6 ee65183555 feat: SoundCloud downloader + rename page to Song Importer
- New src/soundcloud.js: resolves SoundCloud URLs via yt-dlp --dump-single-json,
  renders track/playlist preview with per-track download buttons
- Backend POST /api/soundcloud/resolve: extracts metadata (title, artist, genre,
  artwork, duration) directly from SoundCloud — no iTunes lookup needed
- ytdlp.js: sourceUrl param — if set, downloads directly from URL instead of
  ytsearch cascade (used for SoundCloud tracks)
- Spotify importer page renamed to Song Importer, now contains both
  Spotify and SoundCloud sections in one view

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 20:35:48 +02:00
HoneyandClaude Sonnet 4.6 3a8b879abf feat: use ; as artist separator in downloads, add & handling
navidromeArtist() now writes ; instead of / so Navidrome splits
correctly with the updated Tags.Artist.Split config.
Also handles & (e.g. "Artist A & Artist B" → "Artist A;Artist B").

Add fix-artist-separators.sh — one-time Debian script to update
existing library files from " / " to ";" in artist tags.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 14:26:19 +02:00
HoneyandClaude Sonnet 4.6 4f83eebe79 feat: sort genre pills by total play count via backend
Page loads instantly with song-count order, then silently re-sorts
once the backend aggregates play counts across all songs. Result cached
20 min server-side to avoid repeated full-library fetches.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-23 12:02:25 +02:00
HoneyandClaude Sonnet 4.6 b9a5c6468f refactor: dedup buildTrackList, extract topsong row helper, split romaji to lib
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 11:36:06 +02:00
HoneyandClaude Sonnet 4.6 7bec106350 fix: fetch YTM URLs once and reuse across cascade steps
Each tryYtmSearch() call made a fresh HTTP request, so YouTube could
return different result orderings between steps. The correct video
(right title, wrong channel name) appeared in step 1 but was gone by
step 3 — a worse video with matching keywords slipped through instead.

Now fetch 10 YTM URLs once upfront and filter the same list with
progressively relaxed rules. Also saves 2-4 extra YTM requests per
download.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 20:39:07 +02:00
Honey 757c7045ba fix: normalize title comparison in iTunes lookup to handle Spotify dash-variants vs iTunes paren-variants 2026-05-14 18:53:06 +02:00
HoneyandClaude Sonnet 4.6 0f1e6ff531 refactor: remove dead code from backend and lib
- Remove unused spotifyClientId/spotifyClientSecret from config
- Remove AUDIO_EXTS from metadata exports (internal-only)
- Remove tryYtdlp wrapper in ytdlp.js (direct spawnYtdlp calls)
- Remove _spArtistName wrapper in server (direct _spAllArtists calls)
- Fix stale comment: primary resolver is SpotipyFree, not curl_cffi

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 18:18:50 +02:00
HoneyandClaude Sonnet 4.6 468827571a feat: switch Spotify auth to official Client Credentials Flow
Replaces the broken open.spotify.com/get_access_token scrape with
accounts.spotify.com/api/token (Basic auth, client_credentials grant).
Adds SPOTIFY_CLIENT_ID/SECRET to config, docker-compose, and .env.example.
Health endpoint now reports spotify.configured; frontend disables the
importer and shows a setup guide when credentials are missing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-09 22:57:01 +02:00