From ddf8801db7146455824a328766e03186616c2144 Mon Sep 17 00:00:00 2001 From: tkrmagid Date: Fri, 11 Sep 2026 15:37:23 +0900 Subject: [PATCH] =?UTF-8?q?fix(YoutubeMusic):=20=EA=B2=80=EC=83=89?= =?UTF-8?q?=EC=96=B4-=EC=A0=9C=EB=AA=A9=20=EA=B4=80=EB=A0=A8=EC=84=B1=20?= =?UTF-8?q?=EA=B2=80=EC=82=AC=20=EC=B6=94=EA=B0=80=20-=20=EB=AC=B4?= =?UTF-8?q?=EA=B4=80=ED=95=9C=20=EC=9D=BC=EB=B0=98=EC=98=81=EC=83=81(?= =?UTF-8?q?=ED=86=A0=ED=81=AC=EC=87=BC/=EC=9E=AC=EC=83=9D=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D)=EC=9D=B4=EB=A9=B4=20ytsearch=20Topic=20=ED=8F=B4?= =?UTF-8?q?=EB=B0=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot/src/utils/api/YoutubeMusic.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/bot/src/utils/api/YoutubeMusic.ts b/bot/src/utils/api/YoutubeMusic.ts index 0b84401..19d6bdf 100644 --- a/bot/src/utils/api/YoutubeMusic.ts +++ b/bot/src/utils/api/YoutubeMusic.ts @@ -219,9 +219,18 @@ export const YoutubeMusic = { const lowerQuery = query.toLocaleLowerCase().trim(); if (searchCache.has(lowerQuery)) return searchCache.get(lowerQuery) ?? null; const video = (await this.getSearchFull(query) ?? [])?.[0]; - // 최상위 결과가 커버/MR/노래방류면 null을 반환해, 호출측(LavalinkManager)이 - // 더 깨끗한 `ytsearch:... Topic`(공식 오디오) 폴백을 쓰도록 한다. - if (!video?.url || JUNK_RE.test(video.title)) return null; + if (!video?.url) return null; + // YTM API가 이 계정/엔드포인트에서 음악 카탈로그 '노래'를 주지 못하고 일반 유튜브 영상 + // (토크쇼·재생목록·커버·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); return video.url; }