1
0
mirror of https://github.com/hanxi/xiaomusic.git synced 2025-12-06 14:52:50 +08:00

feat: 监测音乐文件夹变化更新歌曲列表 (#394)

* feat: 监测音乐文件夹变化更新歌曲列表

* fix:增加预设依赖

* Revert "fix:增加预设依赖"

This reverts commit 3705424e98.

* Revert "feat: 监测音乐文件夹变化更新歌曲列表"

This reverts commit 939c59b908.

* feat: 监测音乐文件夹变化更新歌曲列表

新增环境变量:
XIAOMUSIC_ENABLE_FILE_WATCH #控制目录监控开关
XIAOMUSIC_FILE_WATCH_DEBOUNCE  #控制刷新目录任务刷新延迟

也可通过网页设置,默认更换关闭

* fix:设置文字描述修正
This commit is contained in:
AisukaYuki
2025-02-17 17:59:08 +08:00
committed by GitHub
parent 088816b12c
commit 21096b22ea
5 changed files with 90 additions and 0 deletions

View File

@@ -8,6 +8,7 @@ authors = [
dependencies = [
"aiohttp>=3.8.6",
"miservice-fork>=2.7.0",
"watchdog>=6.0.0",
"mutagen>=1.47.0",
"yt-dlp[default]>=2024.12.1.232904.dev0",
"uvicorn>=0.30.1",

View File

@@ -169,6 +169,11 @@ class Config:
continue_play: bool = (
os.getenv("XIAOMUSIC_CONTINUE_PLAY", "false").lower() == "true"
)
# 目录监控配置
enable_file_watch: bool = (
os.getenv("XIAOMUSIC_ENABLE_FILE_WATCH", "false").lower() == "true"
)
file_watch_debounce: int = int(os.getenv("XIAOMUSIC_FILE_WATCH_DEBOUNCE", 10)) # 监控刷新延迟时间(秒)
pull_ask_sec: int = int(os.getenv("XIAOMUSIC_PULL_ASK_SEC", "1"))
enable_pull_ask: bool = (
os.getenv("XIAOMUSIC_ENABLE_PULL_ASK", "true").lower() == "true"

View File

@@ -81,6 +81,15 @@ var vConsole = new window.VConsole();
<label for="music_path">音乐目录:</label>
<input id="music_path" type="text" value="music" />
<label for="enable_file_watch">启用目录监控(自动刷新音乐列表):</label>
<select id="enable_file_watch">
<option value="true">开启</option>
<option value="false" selected>关闭</option>
</select>
<label for="file_watch_debounce">刷新列表延迟时间(秒):</label>
<input id="file_watch_debounce" type="number" value="10" />
<label for="download_path">音乐下载目录(必须是music的子目录):</label>
<input id="download_path" type="text" value='music/download' />

View File

@@ -72,6 +72,15 @@ var vConsole = new window.VConsole();
<label for="music_path">音乐目录:</label>
<input id="music_path" type="text" value="music" />
<label for="enable_file_watch">启用目录监控(自动刷新音乐列表):</label>
<select id="enable_file_watch">
<option value="true">开启</option>
<option value="false" selected>关闭</option>
</select>
<label for="file_watch_debounce">刷新列表延迟时间(秒):</label>
<input id="file_watch_debounce" type="number" value="10" />
<label for="download_path">音乐下载目录(必须是music的子目录):</label>
<input id="download_path" type="text" value='music/download' />

View File

@@ -16,6 +16,9 @@ from logging.handlers import RotatingFileHandler
from aiohttp import ClientSession, ClientTimeout
from miservice import MiAccount, MiIOService, MiNAService, miio_command
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from xiaomusic import __version__
from xiaomusic.analytics import Analytics
from xiaomusic.config import (
@@ -782,11 +785,44 @@ class XiaoMusic:
await self.analytics.send_daily_event()
await asyncio.sleep(3600)
def start_file_watch(self):
if not self.config.enable_file_watch:
self.log.info("目录监控功能已关闭")
return
try:
loop = asyncio.get_running_loop()
except RuntimeError:
loop = asyncio.get_event_loop()
# 延时配置项 file_watch_debounce
self._file_watch_handler = XiaoMusicPathWatch(
callback=self._on_file_change,
debounce_delay=self.config.file_watch_debounce,
loop=loop
)
# 创建监控 music_path 目录对象
self._observer = Observer()
self._observer.schedule(self._file_watch_handler, self.music_path, recursive=True)
self._observer.start()
self.log.info(f"已启动对 {self.music_path} 的目录监控。")
def _on_file_change(self):
self.log.info(f"检测到音乐目录文件变化,正在刷新歌曲列表。")
self._gen_all_music_list()
def stop_file_watch(self):
if hasattr(self, "_observer"):
self._observer.stop()
self._observer.join()
self.log.info("已停止目录监控。")
async def run_forever(self):
self.log.info("run_forever start")
self.try_gen_all_music_tag() # 事件循环开始后调用一次
self.crontab.start()
asyncio.create_task(self.analytics.send_startup_event())
# 取配置 enable_file_watch 循环开始时调用一次,控制目录监控开关
if self.config.enable_file_watch:
self.start_file_watch()
analytics_task = asyncio.create_task(self.analytics_task_daily())
assert (
analytics_task is not None
@@ -1332,6 +1368,8 @@ class XiaoMusic:
self.log.info("save_cur_config ok")
def update_config_from_setting(self, data):
# 保存之前的 enable_file_watch 配置
pre_efw = self.config.enable_file_watch
# 自动赋值相同字段的配置
self.config.update_config(data)
@@ -1343,6 +1381,15 @@ class XiaoMusic:
self.log.info(f"语音控制已启动, 用【{joined_keywords}】开头来控制")
self.log.debug(f"key_word_dict: {self.config.key_word_dict}")
# 检查 enable_file_watch 配置是否发生变化
now_efw = self.config.enable_file_watch
if pre_efw != now_efw:
self.log.info("配置更新:{}目录监控".format("开启" if now_efw else "关闭"))
if now_efw:
self.start_file_watch()
else:
self.stop_file_watch()
# 重新加载计划任务
self.crontab.reload_config(self)
@@ -2097,3 +2144,22 @@ class XiaoMusicDevice:
if name in self.xiaomusic.music_list.get("所有电台", []):
return "所有电台"
return "全部"
# 目录监控类,使用延迟防抖
class XiaoMusicPathWatch(FileSystemEventHandler):
def __init__(self, callback, debounce_delay, loop):
self.callback = callback
self.debounce_delay = debounce_delay
self.loop = loop
self._debounce_handle = None
def on_any_event(self, event):
self.schedule_callback()
def schedule_callback(self):
def _execute_callback():
self._debounce_handle = None
self.callback()
if self._debounce_handle:
self._debounce_handle.cancel()
self._debounce_handle = self.loop.call_later(self.debounce_delay, _execute_callback)