1
0
mirror of https://github.com/hanxi/xiaomusic.git synced 2025-12-07 15:02:55 +08:00

Compare commits

...

5 Commits

Author SHA1 Message Date
涵曦
5aff72dbb6 bump: version 0.1.97 → 0.1.98 2024-07-07 05:48:40 +00:00
涵曦
043f452e71 Update README.md 2024-07-07 13:47:30 +08:00
涵曦
5cedf8a907 fix: 修复多设备获取不到对话记录的问题 see #65 2024-07-07 04:46:33 +00:00
涵曦
ae77c7232e Update README.md 2024-07-07 11:42:05 +08:00
涵曦
d559413d46 fix: #93 修复目录深度设置后导致目录下的歌曲无法加到播放列表里的问题 2024-07-07 02:03:17 +00:00
6 changed files with 74 additions and 86 deletions

View File

@@ -1,3 +1,10 @@
## v0.1.98 (2024-07-07)
### Fix
- 修复多设备获取不到对话记录的问题 see #65
- #93 修复目录深度设置后导致目录下的歌曲无法加到播放列表里的问题
## v0.1.97 (2024-07-06)
### Fix

View File

@@ -39,9 +39,9 @@ docker run -p 8090:8090 \
hanxi/xiaomusic
```
启动成功后,在 web 页面可以配置其他参数,带有 `*` 号的配置是必须要配置的,其他的用不上时不用修改。
启动成功后,在 web 页面可以配置其他参数,带有 `*` 号的配置是必须要配置的,其他的用不上时不用修改。初次配置时需要在页面上输入小米账号和密码保存后才能获取到设备列表。
### ✨ 修改8090端口
### ✨✨✨ 修改默认8090端口映射 ✨✨✨
如果需要修改 8090 端口为其他端口,比如 5678需要这样配3个数字都需要是 5678 。见 <https://github.com/hanxi/xiaomusic/issues/19>

View File

@@ -1,6 +1,6 @@
[project]
name = "xiaomusic"
version = "0.1.97"
version = "0.1.98"
description = "Play Music with xiaomi AI speaker"
authors = [
{name = "涵曦", email = "im.hanxi@gmail.com"},

View File

@@ -1 +1 @@
__version__ = "0.1.97"
__version__ = "0.1.98"

View File

@@ -101,63 +101,48 @@ def custom_sort_key(s):
return (2, s)
# fork from https://gist.github.com/dougthor42/001355248518bc64d2f8
def walk_to_depth(root, depth=None, *args, **kwargs):
"""
Wrapper around os.walk that stops after going down `depth` folders.
I had my own version, but it wasn't as efficient as
http://stackoverflow.com/a/234329/1354930, so I modified to be more
similar to nosklo's answer.
However, nosklo's answer doesn't work if topdown=False, so I kept my
version.
"""
# Let people use this as a standard `os.walk` function.
if depth is None:
return os.walk(root, *args, **kwargs)
def _get_depth_path(root, directory, depth):
# 计算当前目录的深度
relative_path = root[len(directory) :].strip(os.sep)
path_parts = relative_path.split(os.sep)
if len(path_parts) >= depth:
return os.path.join(directory, *path_parts[:depth])
else:
return root
# remove any trailing separators so that our counts are correct.
root = root.rstrip(os.path.sep)
def main_func(root, depth, *args, **kwargs):
"""Faster because it skips traversing dirs that are too deep."""
root_depth = root.count(os.path.sep)
for dirpath, dirnames, filenames in os.walk(root, *args, **kwargs):
yield (dirpath, dirnames, filenames)
def _append_files_result(result, root, joinpath, files, support_extension):
dir_name = os.path.basename(root)
if dir_name not in result:
result[dir_name] = []
for file in files:
# 过滤隐藏文件
if file.startswith("."):
continue
# 过滤文件后缀
(name, extension) = os.path.splitext(file)
if extension.lower() not in support_extension:
continue
# calculate how far down we are.
current_folder_depth = dirpath.count(os.path.sep)
if current_folder_depth >= root_depth + depth:
del dirnames[:]
result[dir_name].append(os.path.join(joinpath, file))
def fallback_func(root, depth, *args, **kwargs):
"""Slower, but works when topdown is False"""
root_depth = root.count(os.path.sep)
for dirpath, dirnames, filenames in os.walk(root, *args, **kwargs):
current_folder_depth = dirpath.count(os.path.sep)
if current_folder_depth <= root_depth + depth:
yield (dirpath, dirnames, filenames)
# there's gotta be a better way do do this...
try:
if args[0] is False:
yield from fallback_func(root, depth, *args, **kwargs)
return
def traverse_music_directory(
directory, depth=10, exclude_dirs=None, support_extension=None
):
result = {}
for root, dirs, files in os.walk(directory):
# 忽略排除的目录
dirs[:] = [d for d in dirs if d not in exclude_dirs]
# 计算当前目录的深度
current_depth = root[len(directory) :].count(os.sep) + 1
if current_depth > depth:
depth_path = _get_depth_path(root, directory, depth - 1)
_append_files_result(result, depth_path, root, files, support_extension)
else:
yield from main_func(root, depth, *args, **kwargs)
return
except IndexError:
pass
try:
if kwargs["topdown"] is False:
yield from fallback_func(root, depth, *args, **kwargs)
return
else:
yield from main_func(root, depth, *args, **kwargs)
return
except KeyError:
yield from main_func(root, depth, *args, **kwargs)
return
_append_files_result(result, root, root, files, support_extension)
return result
def downloadfile(url):

View File

@@ -37,7 +37,7 @@ from xiaomusic.utils import (
get_local_music_duration,
get_web_music_duration,
parse_cookie_string,
walk_to_depth,
traverse_music_directory,
)
EOF = object()
@@ -198,12 +198,12 @@ class XiaoMusic:
self.device2hardware = {}
self.did2device = {}
for h in hardware_data:
device = h.get("deviceID", "")
device_id = h.get("deviceID", "")
hardware = h.get("hardware", "")
did = h.get("miotDID", "")
if device and hardware and did and (did in mi_dids):
self.device2hardware[device] = hardware
self.did2device[did] = device
if device_id and hardware and did and (did in mi_dids):
self.device2hardware[device_id] = hardware
self.did2device[did] = device_id
except Exception as e:
self.log.error(f"Execption {e}")
@@ -236,8 +236,9 @@ class XiaoMusic:
for i in range(retries):
try:
timeout = ClientTimeout(total=15)
hardware = self.device2hardware[device_id]
url = LATEST_ASK_API.format(
hardware=self.config.hardware,
hardware=hardware,
timestamp=str(int(time.time() * 1000)),
)
self.log.debug(f"url:{url}")
@@ -481,39 +482,34 @@ class XiaoMusic:
encoded_name = urllib.parse.quote(filename)
return f"http://{self.hostname}:{self.public_port}/{encoded_name}"
# 递归获取目录下所有歌曲,生成随机播放列表
# 获取目录下所有歌曲,生成随机播放列表
def _gen_all_music_list(self):
self._all_music = {}
all_music_by_dir = {}
for root, dirs, filenames in walk_to_depth(
self.music_path, depth=self.music_path_depth
):
dirs[:] = [d for d in dirs if d not in self.exclude_dirs]
self.log.debug("root:%s dirs:%s music_path:%s", root, dirs, self.music_path)
dir_name = os.path.basename(root)
if self.music_path == root:
local_musics = traverse_music_directory(
self.music_path,
depth=self.music_path_depth,
exclude_dirs=self.exclude_dirs,
support_extension=SUPPORT_MUSIC_TYPE,
)
for dir_name, files in local_musics.items():
if len(files) == 0:
continue
if dir_name == os.path.basename(self.music_path):
dir_name = "其他"
if self.music_path != self.download_path and dir_name == os.path.basename(
self.download_path
):
dir_name = "下载"
if dir_name not in all_music_by_dir:
all_music_by_dir[dir_name] = {}
for filename in filenames:
self.log.debug("gen_all_music_list. filename:%s", filename)
# 过滤隐藏文件
if filename.startswith("."):
continue
# 过滤非音乐文件
(name, extension) = os.path.splitext(filename)
self.log.debug(
"gen_all_music_list. filename:%s, name:%s, extension:%s",
filename,
name,
extension,
)
if extension.lower() not in SUPPORT_MUSIC_TYPE:
continue
for file in files:
# 歌曲名字相同会覆盖
self._all_music[name] = os.path.join(root, filename)
filename = os.path.basename(file)
(name, _) = os.path.splitext(filename)
self._all_music[name] = file
all_music_by_dir[dir_name][name] = True
self._play_list = list(self._all_music.keys())
self._cur_play_list = "全部"
self._gen_play_list()