fix(YoutubeMusic): 검색어-제목 관련성 검사 추가 - 무관한 일반영상(토크쇼/재생목록)이면 ytsearch Topic 폴백

This commit is contained in:
tkrmagid
2026-09-11 15:37:23 +09:00
parent fd92995255
commit ddf8801db7

View File

@@ -219,9 +219,18 @@ export const YoutubeMusic = {
const lowerQuery = query.toLocaleLowerCase().trim(); const lowerQuery = query.toLocaleLowerCase().trim();
if (searchCache.has(lowerQuery)) return searchCache.get(lowerQuery) ?? null; if (searchCache.has(lowerQuery)) return searchCache.get(lowerQuery) ?? null;
const video = (await this.getSearchFull(query) ?? [])?.[0]; const video = (await this.getSearchFull(query) ?? [])?.[0];
// 최상위 결과가 커버/MR/노래방류면 null을 반환해, 호출측(LavalinkManager)이 if (!video?.url) return null;
// 더 깨끗한 `ytsearch:... Topic`(공식 오디오) 폴백을 쓰도록 한다. // YTM API가 이 계정/엔드포인트에서 음악 카탈로그 '노래'를 주지 못하고 일반 유튜브 영상
if (!video?.url || JUNK_RE.test(video.title)) return null; // (토크쇼·재생목록·커버·MR 등)을 반환하는 경우가 많다. 그래서 (1)커버/MR류거나 (2)제목이
// 검색어와 충분히 일치하지 않으면 null을 반환해, 호출측이 더 깨끗한 `ytsearch:... Topic`
// (공식 오디오) 폴백을 쓰도록 한다.
if (JUNK_RE.test(video.title)) return null;
const titleLower = video.title.toLocaleLowerCase();
const tokens = lowerQuery.split(/\s+/).filter((t) => t.length >= 2);
if (tokens.length > 0) {
const hit = tokens.filter((t) => titleLower.includes(t)).length;
if (hit / tokens.length < 0.5) return null; // 관련성 낮음 → 폴백
}
searchCache.set(lowerQuery, video.url); searchCache.set(lowerQuery, video.url);
return video.url; return video.url;
} }