From 86b35bda9a5fb2b16e86d8d3f24b0e8c65ca8026 Mon Sep 17 00:00:00 2001 From: jxxghp Date: Thu, 13 Aug 2026 21:53:18 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BC=98=E5=85=88=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E7=AE=80=E4=BD=93=E9=9F=B3=E4=B9=90=E5=85=B3=E9=94=AE=E8=AF=8D?= =?UTF-8?q?=E6=90=9C=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/chain/search.py | 10 ++++++++-- tests/test_music_search.py | 32 ++++++++++++++++++++++++++++++++ tests/test_music_workflows.py | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/app/chain/search.py b/app/chain/search.py index d49c1ebd4..a8c7d880e 100644 --- a/app/chain/search.py +++ b/app/chain/search.py @@ -62,7 +62,7 @@ class SearchChain(ChainBase): @classmethod def music_site_keywords(cls, music: MetaMusic | MusicInfo) -> list[str]: - """按实体生成站点关键词,先扩大名称召回,再由结果匹配校验艺术家。""" + """按实体生成站点关键词,繁体字段优先使用简体写法扩大召回。""" artists = music.artists or [] artist = artists[0] if artists else music.album_artist values: list[Optional[str]] = [] @@ -74,7 +74,13 @@ class SearchChain(ChainBase): music.title, f"{artist} {music.title}" if artist and music.title else None, ]) - return cls._unique_music_texts(values) + search_values: list[Optional[str]] = [] + for value in values: + search_values.extend([ + zhconv_convert(value, "zh-hans") if value else None, + value, + ]) + return cls._unique_music_texts(search_values) @classmethod def matches_music_resource( diff --git a/tests/test_music_search.py b/tests/test_music_search.py index 9702f3b83..2b9c4517c 100644 --- a/tests/test_music_search.py +++ b/tests/test_music_search.py @@ -82,6 +82,38 @@ def test_music_search_continues_after_unrelated_first_keyword_results(): assert contexts[0].torrent_info.title == matched.title +def test_music_search_uses_simplified_keywords_before_original_traditional_keywords(): + """媒体信息含繁体时应先请求简体关键词,未命中后再请求繁体原文。""" + chain = SearchChain() + music = MusicInfo( + media_source="musicbrainz", + media_id="album-1", + music_type="album", + title="永遠是朋友", + album="永遠是朋友", + artists=["周華健"], + ) + matched = TorrentInfo( + title="周華健 - 永遠是朋友 FLAC", + category=MediaType.MUSIC.value, + site_name="MusicSite", + ) + + with patch.object( + chain, + "_SearchChain__search_all_sites", + side_effect=[[], [matched]], + ) as search_sites, patch("app.chain.search.time.sleep"): + contexts = chain._process_music(music, rule_groups=[]) + + assert [call.kwargs["keyword"] for call in search_sites.call_args_list] == [ + "永远是朋友", + "永遠是朋友", + ] + assert len(contexts) == 1 + assert contexts[0].torrent_info.title == matched.title + + def test_music_search_matches_artist_from_resource_description(): """精确音乐搜索应使用副标题中的艺术家,兼容主标题只有曲名的站点。""" music = MusicInfo( diff --git a/tests/test_music_workflows.py b/tests/test_music_workflows.py index e6f84aa72..cfee69df1 100644 --- a/tests/test_music_workflows.py +++ b/tests/test_music_workflows.py @@ -100,6 +100,40 @@ def test_build_site_keywords_searches_track_before_combined_artist(): ] +def test_build_site_keywords_places_simplified_album_terms_before_original_terms(): + """繁体专辑信息应先搜索简体名称及组合词,再回退原文且不单搜艺术家。""" + info = MusicInfo( + music_type="album", + title="永遠是朋友", + artists=["周華健"], + album="永遠是朋友", + ) + + assert SearchChain.music_site_keywords(info) == [ + "永远是朋友", + "永遠是朋友", + "周华健 永远是朋友", + "周華健 永遠是朋友", + ] + + +def test_build_site_keywords_places_simplified_recording_terms_before_original_terms(): + """繁体单曲信息应先搜索简体曲名及组合词,不生成仅艺术家的关键词。""" + info = MusicInfo( + music_type="recording", + title="後來", + artists=["劉若英"], + album="我等你", + ) + + assert SearchChain.music_site_keywords(info) == [ + "后来", + "後來", + "刘若英 后来", + "劉若英 後來", + ] + + def test_album_resource_match_requires_selected_album_title(): """专辑订阅只接受同时包含目标专辑名和艺术家的站点资源。""" album = MusicInfo(