From 40efa207bbdc4b0490f1dfecc2a2d21c2dd64ddd Mon Sep 17 00:00:00 2001 From: Honey Date: Mon, 25 May 2026 18:20:15 +0200 Subject: [PATCH] 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 --- backend/lib/ytdlp.js | 55 ++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/backend/lib/ytdlp.js b/backend/lib/ytdlp.js index ed741a8..dd0001f 100644 --- a/backend/lib/ytdlp.js +++ b/backend/lib/ytdlp.js @@ -81,6 +81,34 @@ async function downloadTrack({ jobId, artist, rawArtist, albumArtist, title, alb // rawArtist is undefined for non-Japanese tracks, so fall back to mainArtist. const ytmArtist = (rawArtist || mainArtist).replace(/\p{S}/gu, '').trim(); const searchArtist = ytmArtist; + + const escRe = s => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + const JP_CHARS = /[ぁ-んァ-ン一-龯]/; + + const variantFilter = buildVariantFilter(title); + const titleKws = buildTitleKeywords(title); + const variantPart = variantFilter ? ` & ${variantFilter}` : ''; + const titleKwPart = titleKws.length ? titleKws.map(k => ` & title ~= (?i)${k}`).join('') : ''; + + // Soft channel check: first word of original artist name used in early cascade steps to avoid + // downloading a same-title song by a different artist (e.g. wrong "Moonlight" for N!GHT). + // Skip when artistFirstWord is non-ASCII (Japanese kanji/kana): YouTube channel names are + // almost never in kanji, so the filter would reject every valid result. + const artistFirstWord = (rawArtist || mainArtist).split(/[\s,/]+/)[0]; + const artistChannelPart = (artistFirstWord.length >= 3 && !JP_CHARS.test(artistFirstWord)) + ? ` & channel ~= (?i)${escRe(artistFirstWord)}` : ''; + + // When the title is Japanese (keywords stripped to nothing) OR when we have an album that + // provides better search context, include the album's first two words in the search query. + // This helps YTM rank the official OST/album track above fan covers and romaji-subtitle uploads. + // Only use album words that are ASCII (romaji/English) — Japanese album words don't help YTM ranking. + const hasJpTitle = JP_CHARS.test(title); + const albumWords = (album && album !== 'Singles' && album !== 'Unknown') + ? album.split(/\s+/).filter(w => /^[A-Za-z0-9]/.test(w)).slice(0, 2).join(' ') + : ''; + const albumQuerySuffix = (hasJpTitle || (albumWords && titleKws.length <= 1)) && albumWords + ? ' ' + albumWords : ''; + const query = `${ytmArtist} - ${title}${albumQuerySuffix}`; const baseArgs = [ @@ -167,33 +195,6 @@ async function downloadTrack({ jobId, artist, rawArtist, albumArtist, title, alb proc.on('close', () => resolve(channelExpanded ? [] : urls)); }); - const escRe = s => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); - const JP_CHARS = /[ぁ-んァ-ン一-龯]/; - - const variantFilter = buildVariantFilter(title); - const titleKws = buildTitleKeywords(title); - const variantPart = variantFilter ? ` & ${variantFilter}` : ''; - const titleKwPart = titleKws.length ? titleKws.map(k => ` & title ~= (?i)${k}`).join('') : ''; - - // Soft channel check: first word of original artist name used in early cascade steps to avoid - // downloading a same-title song by a different artist (e.g. wrong "Moonlight" for N!GHT). - // Skip when artistFirstWord is non-ASCII (Japanese kanji/kana): YouTube channel names are - // almost never in kanji, so the filter would reject every valid result. - const artistFirstWord = (rawArtist || mainArtist).split(/[\s,/]+/)[0]; - const artistChannelPart = (artistFirstWord.length >= 3 && !JP_CHARS.test(artistFirstWord)) - ? ` & channel ~= (?i)${escRe(artistFirstWord)}` : ''; - - // When the title is Japanese (keywords stripped to nothing) OR when we have an album that - // provides better search context, include the album's first two words in the search query. - // This helps YTM rank the official OST/album track above fan covers and romaji-subtitle uploads. - // Only use album words that are ASCII (romaji/English) — Japanese album words don't help YTM ranking. - const hasJpTitle = JP_CHARS.test(title); - const albumWords = (album && album !== 'Singles' && album !== 'Unknown') - ? album.split(/\s+/).filter(w => /^[A-Za-z0-9]/.test(w)).slice(0, 2).join(' ') - : ''; - const albumQuerySuffix = (hasJpTitle || (albumWords && titleKws.length <= 1)) && albumWords - ? ' ' + albumWords : ''; - const mf = (dur, variant, strict = false) => { const durPart = dur ? `duration > ${dur.min} & duration < ${dur.max} & ` : ''; return ['--match-filter',