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:
@@ -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 = (
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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:
|
||||
"""
|
||||
解析字符串为字典
|
||||
|
||||
Reference in New Issue
Block a user