From ed8411c4db5e80a8186c27d6022f4455203f52c0 Mon Sep 17 00:00:00 2001 From: jokinas <89495587+jokinas@users.noreply.github.com> Date: Wed, 20 May 2026 20:48:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=92=AD=E6=94=BE=E6=9C=AC=E5=9C=B0?= =?UTF-8?q?=E9=9F=B3=E4=B9=90=E6=94=AF=E6=8C=81=E4=B8=80=E6=9D=A1=E6=8C=87?= =?UTF-8?q?=E4=BB=A4=E5=AE=8C=E6=88=90=E6=90=9C=E7=B4=A2+=E9=80=89?= =?UTF-8?q?=E6=8B=A9=20(#880)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * style: ruff lint and format fix * fix: 恢复脚本文件的可执行权限属性 * feat: 播放本地音乐支持一条指令完成搜索+选择(如:播放本地音乐周杰伦第二个) --- xiaomusic/device_player.py | 46 ++++++++++++++++++++++++++++++++--- xiaomusic/music_library.py | 4 ++- xiaomusic/utils/text_utils.py | 37 ++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 5 deletions(-) diff --git a/xiaomusic/device_player.py b/xiaomusic/device_player.py index db50403..b613490 100644 --- a/xiaomusic/device_player.py +++ b/xiaomusic/device_player.py @@ -29,7 +29,11 @@ from xiaomusic.const import ( ) from xiaomusic.events import DEVICE_CONFIG_CHANGED from xiaomusic.utils.file_utils import chmodfile -from xiaomusic.utils.text_utils import custom_sort_key, list2str +from xiaomusic.utils.text_utils import ( + custom_sort_key, + list2str, + parse_ordinal_suffix, +) class XiaoMusicDevice: @@ -314,15 +318,49 @@ class XiaoMusicDevice: self.log.info(f"没有歌曲播放了 name:{name} search_key:{search_key}") return - # 模糊搜索(支持多结果选择) max_results = self.config.fuzzy_match_max_results - names = self.xiaomusic.music_library.find_real_music_name(name, n=max_results) - self.log.info(f"play_internal. 搜索关键词:{name} 匹配数量:{len(names)}") + auto_index = None + + parsed_name, parsed_index = parse_ordinal_suffix(name) + if parsed_index is not None: + full_names = self.xiaomusic.music_library.find_real_music_name( + name, n=max_results + ) + if full_names: + self.log.info( + f"完整名称'{name}'有{len(full_names)}条匹配,优先使用完整名称搜索" + ) + names = full_names + else: + self.log.info( + f"完整名称'{name}'无匹配,使用'{parsed_name}'搜索并自动选择第{parsed_index}个" + ) + name = parsed_name + search_key = parsed_name + auto_index = parsed_index + names = self.xiaomusic.music_library.find_real_music_name( + name, n=max_results + ) + else: + names = self.xiaomusic.music_library.find_real_music_name( + name, n=max_results + ) + + self.log.info( + f"play_internal. 搜索关键词:{name} 匹配数量:{len(names)} auto_index:{auto_index}" + ) if len(names) > 1: for idx, music_name in enumerate(names, 1): self.log.info(f" 第{idx}个: {music_name}") if len(names) > 1: + if auto_index is not None and 1 <= auto_index <= len(names): + self._pending_selection = names + self._pending_selection_count = len(names) + self.log.info(f"自动选择第{auto_index}个: {names[auto_index - 1]}") + await self.handle_selection(auto_index) + return + self._pending_selection = names self._pending_selection_count = len(names) selection_text = ( diff --git a/xiaomusic/music_library.py b/xiaomusic/music_library.py index 6634080..d92ce13 100644 --- a/xiaomusic/music_library.py +++ b/xiaomusic/music_library.py @@ -611,7 +611,9 @@ class MusicLibrary: extra_search_index=self._extra_index_search, ) real_names.sort(key=custom_sort_key) - self.log.info(f"没找到歌曲【{name}】") + if not real_names: + self.log.info(f"没找到歌曲【{name}】") + return [] return real_names[:n] def find_real_music_list_name(self, list_name): diff --git a/xiaomusic/utils/text_utils.py b/xiaomusic/utils/text_utils.py index 79dd0e6..af4605c 100644 --- a/xiaomusic/utils/text_utils.py +++ b/xiaomusic/utils/text_utils.py @@ -220,6 +220,43 @@ def chinese_to_number(chinese: str) -> int: return result +_ORDINAL_SUFFIX_RE = re.compile( + r"^(.+?)(第[零一二三四五六七八九十百千万亿]+[个首条集部曲期版])$" +) + + +def parse_ordinal_suffix(text): + """从文本末尾解析序号后缀 + + 例如:"爸爸的头不见了第二个" → ("爸爸的头不见了", 2) + "爸爸的头不见了第三集" → ("爸爸的头不见了", 3) + + Args: + text: 待解析的文本 + + Returns: + tuple: (基础文本, 序号) 或 (原始文本, None) + """ + if not text: + return text, None + + match = _ORDINAL_SUFFIX_RE.match(text) + if not match: + return text, None + + base_text = match.group(1) + ordinal_part = match.group(2) + num_match = re.match(r"第([零一二三四五六七八九十百千万亿]+)", ordinal_part) + if not num_match: + return text, None + + index = chinese_to_number(num_match.group(1)) + if index < 1: + return text, None + + return base_text, index + + def parse_str_to_dict(s: str, d1: str = ",", d2: str = ":") -> dict: """ 解析字符串为字典