1
0
mirror of https://github.com/hanxi/xiaomusic.git synced 2026-06-01 12:15:48 +08:00

feat: 播放本地音乐支持一条指令完成搜索+选择 (#880)

* style: ruff lint and format fix

* fix: 恢复脚本文件的可执行权限属性

* feat: 播放本地音乐支持一条指令完成搜索+选择(如:播放本地音乐周杰伦第二个)
This commit is contained in:
jokinas
2026-05-20 20:48:56 +08:00
committed by GitHub
parent cc01663599
commit ed8411c4db
3 changed files with 82 additions and 5 deletions

View File

@@ -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 = (

View File

@@ -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):

View File

@@ -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:
"""
解析字符串为字典