From d559413d4672ce40e2cf0bd458690b6ba21f14b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B6=B5=E6=9B=A6?= Date: Sun, 7 Jul 2024 02:03:17 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20#93=20=E4=BF=AE=E5=A4=8D=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=E6=B7=B1=E5=BA=A6=E8=AE=BE=E7=BD=AE=E5=90=8E=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E7=9B=AE=E5=BD=95=E4=B8=8B=E7=9A=84=E6=AD=8C=E6=9B=B2?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E5=8A=A0=E5=88=B0=E6=92=AD=E6=94=BE=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E9=87=8C=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- xiaomusic/utils.py | 87 +++++++++++++++++------------------------- xiaomusic/xiaomusic.py | 47 ++++++++++------------- 2 files changed, 57 insertions(+), 77 deletions(-) diff --git a/xiaomusic/utils.py b/xiaomusic/utils.py index 2a21057..6549886 100644 --- a/xiaomusic/utils.py +++ b/xiaomusic/utils.py @@ -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): diff --git a/xiaomusic/xiaomusic.py b/xiaomusic/xiaomusic.py index c66b84c..4e67648 100644 --- a/xiaomusic/xiaomusic.py +++ b/xiaomusic/xiaomusic.py @@ -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() @@ -481,39 +481,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()