fix(monitor): 优先按目录配置识别音乐

This commit is contained in:
jxxghp
2026-08-09 21:19:43 +08:00
parent 393a4ca4e2
commit d03307b687
2 changed files with 82 additions and 1 deletions

View File

@@ -8,8 +8,10 @@ from app.chain.transfer import TransferChain
from app.core.cache import TTLCache from app.core.cache import TTLCache
from app.core.config import settings from app.core.config import settings
from app.db.transferhistory_oper import TransferHistoryOper from app.db.transferhistory_oper import TransferHistoryOper
from app.helper.directory import DirectoryHelper
from app.log import logger from app.log import logger
from app.schemas import FileItem from app.schemas import FileItem
from app.schemas.types import MediaType
class TransferDispatcher: class TransferDispatcher:
@@ -97,6 +99,39 @@ class TransferDispatcher:
""" """
return f"{storage}:{Path(event_path).as_posix()}" return f"{storage}:{Path(event_path).as_posix()}"
@staticmethod
def _get_monitor_media_type(storage: str, event_path: Path) -> Optional[MediaType]:
"""
获取事件路径命中的目录监控媒体类型,嵌套配置优先使用最具体的根目录。
:param storage: 存储
:param event_path: 事件文件路径
:return: 配置的媒体类型,未配置或无匹配目录时返回 None
"""
matching_dirs = [
dir_info
for dir_info in DirectoryHelper().get_download_dirs()
if dir_info.monitor_type == "monitor"
and dir_info.storage == storage
and event_path.is_relative_to(Path(dir_info.download_path))
]
if not matching_dirs:
return None
dir_info = max(
matching_dirs,
key=lambda item: len(Path(item.download_path).parts),
)
if not dir_info.media_type:
return None
try:
return MediaType(dir_info.media_type)
except ValueError:
logger.warning(
f"目录监控 {dir_info.download_path} 配置了未知媒体类型:{dir_info.media_type}"
)
return None
def _register_pending(self, storage: str, event_path: Path, file_size: float = None): def _register_pending(self, storage: str, event_path: Path, file_size: float = None):
""" """
登记历史查询失败的文件待重试,重复失败累计次数,超限后放弃。 登记历史查询失败的文件待重试,重复失败累计次数,超限后放弃。
@@ -202,7 +237,11 @@ class TransferDispatcher:
basename=event_path.stem, basename=event_path.stem,
extension=event_path.suffix[1:], extension=event_path.suffix[1:],
size=file_size size=file_size
) ),
mtype=self._get_monitor_media_type(
storage=storage,
event_path=event_path,
),
) )
return True return True
except Exception as e: except Exception as e:

View File

@@ -5,6 +5,8 @@ from watchfiles import Change
from app.monitor import DirectoryChangeEvent, LocalDirectoryWatcher, Monitor from app.monitor import DirectoryChangeEvent, LocalDirectoryWatcher, Monitor
from app.monitor.dispatcher import TransferDispatcher from app.monitor.dispatcher import TransferDispatcher
from app.schemas import TransferDirectoryConf
from app.schemas.types import MediaType
class CallbackRecorder: class CallbackRecorder:
@@ -302,3 +304,43 @@ def test_handle_file_invokes_transfer_when_history_missing(monkeypatch):
assert fileitem.storage == "local" assert fileitem.storage == "local"
assert fileitem.path == event_path.as_posix() assert fileitem.path == event_path.as_posix()
assert fileitem.size == 1024 assert fileitem.size == 1024
def test_handle_file_prefers_music_type_from_monitor_directory(monkeypatch):
"""音乐目录监控触发整理时应透传音乐类型,避免音频按影视名称识别。"""
dispatcher = TransferDispatcher(all_exts=[".flac"], cache={})
event_path = Path("/downloads/music/album/track.flac")
directories = [
TransferDirectoryConf(
storage="local",
download_path="/downloads",
media_type=MediaType.MOVIE.value,
monitor_type="monitor",
),
TransferDirectoryConf(
storage="local",
download_path="/downloads/music",
media_type=MediaType.MUSIC.value,
monitor_type="monitor",
),
]
transfer_chain_instance = MagicMock()
monkeypatch.setattr(dispatcher, "_has_transfer_history", MagicMock(return_value=False))
monkeypatch.setattr(
"app.monitor.dispatcher.DirectoryHelper",
MagicMock(return_value=MagicMock(get_download_dirs=MagicMock(return_value=directories))),
)
monkeypatch.setattr(
"app.monitor.dispatcher.TransferChain",
MagicMock(return_value=transfer_chain_instance),
)
handled = dispatcher.handle_file(
storage="local",
event_path=event_path,
file_size=1024,
)
assert handled
assert transfer_chain_instance.do_transfer.call_args.kwargs["mtype"] == MediaType.MUSIC