mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 23:47:41 +08:00
fix: 修复订阅自定义识别词在整理时不生效的问题
问题:订阅中添加的自定义识别词(特别是集数偏移)在下载时正常生效, 但在下载完成整理时没有生效。 根因:下载历史中未保存识别词,整理时 MetaInfoPath 未接收 custom_words 参数。 修复: - 在 DownloadHistory 模型中添加 custom_words 字段 - 下载时从 meta.apply_words 获取并保存识别词到下载历史 - MetaInfoPath 函数添加 custom_words 参数支持 - 整理时从下载历史获取 custom_words 并传递给 MetaInfoPath - 添加 Alembic 迁移脚本 (2.2.3) - 添加相关单元测试
This commit is contained in:
@@ -292,6 +292,10 @@ class DownloadChain(ChainBase):
|
|||||||
|
|
||||||
# 登记下载记录
|
# 登记下载记录
|
||||||
downloadhis = DownloadHistoryOper()
|
downloadhis = DownloadHistoryOper()
|
||||||
|
# 获取应用的识别词(如果有)
|
||||||
|
custom_words_str = None
|
||||||
|
if hasattr(_meta, 'apply_words') and _meta.apply_words:
|
||||||
|
custom_words_str = '\n'.join(_meta.apply_words)
|
||||||
downloadhis.add(
|
downloadhis.add(
|
||||||
path=download_path.as_posix(),
|
path=download_path.as_posix(),
|
||||||
type=_media.type.value,
|
type=_media.type.value,
|
||||||
@@ -315,6 +319,7 @@ class DownloadChain(ChainBase):
|
|||||||
date=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
|
date=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
|
||||||
media_category=_media.category,
|
media_category=_media.category,
|
||||||
episode_group=_media.episode_group,
|
episode_group=_media.episode_group,
|
||||||
|
custom_words=custom_words_str,
|
||||||
note={"source": source}
|
note={"source": source}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+19
-14
@@ -1080,9 +1080,26 @@ class TransferChain(ChainBase, metaclass=Singleton):
|
|||||||
err_msgs.append(f"{file_item.name} 已整理过")
|
err_msgs.append(f"{file_item.name} 已整理过")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# 提前获取下载历史,以便获取自定义识别词
|
||||||
|
download_history = None
|
||||||
|
downloadhis = DownloadHistoryOper()
|
||||||
|
if bluray_dir:
|
||||||
|
# 蓝光原盘,按目录名查询
|
||||||
|
download_history = downloadhis.get_by_path(file_path.as_posix())
|
||||||
|
else:
|
||||||
|
# 按文件全路径查询
|
||||||
|
download_file = downloadhis.get_file_by_fullpath(file_path.as_posix())
|
||||||
|
if download_file:
|
||||||
|
download_history = downloadhis.get_by_hash(download_file.download_hash)
|
||||||
|
|
||||||
|
# 获取自定义识别词
|
||||||
|
custom_words_list = None
|
||||||
|
if download_history and download_history.custom_words:
|
||||||
|
custom_words_list = download_history.custom_words.split('\n')
|
||||||
|
|
||||||
if not meta:
|
if not meta:
|
||||||
# 文件元数据
|
# 文件元数据(传入自定义识别词)
|
||||||
file_meta = MetaInfoPath(file_path)
|
file_meta = MetaInfoPath(file_path, custom_words=custom_words_list)
|
||||||
else:
|
else:
|
||||||
file_meta = meta
|
file_meta = meta
|
||||||
|
|
||||||
@@ -1108,18 +1125,6 @@ class TransferChain(ChainBase, metaclass=Singleton):
|
|||||||
if end_ep is not None:
|
if end_ep is not None:
|
||||||
file_meta.end_episode = end_ep
|
file_meta.end_episode = end_ep
|
||||||
|
|
||||||
# 根据父路径获取下载历史
|
|
||||||
download_history = None
|
|
||||||
downloadhis = DownloadHistoryOper()
|
|
||||||
if bluray_dir:
|
|
||||||
# 蓝光原盘,按目录名查询
|
|
||||||
download_history = downloadhis.get_by_path(file_path.as_posix())
|
|
||||||
else:
|
|
||||||
# 按文件全路径查询
|
|
||||||
download_file = downloadhis.get_file_by_fullpath(file_path.as_posix())
|
|
||||||
if download_file:
|
|
||||||
download_history = downloadhis.get_by_hash(download_file.download_hash)
|
|
||||||
|
|
||||||
# 获取下载Hash
|
# 获取下载Hash
|
||||||
if download_history and (not downloader or not download_hash):
|
if download_history and (not downloader or not download_hash):
|
||||||
downloader = download_history.downloader
|
downloader = download_history.downloader
|
||||||
|
|||||||
@@ -62,20 +62,21 @@ def MetaInfo(title: str, subtitle: Optional[str] = None, custom_words: List[str]
|
|||||||
return meta
|
return meta
|
||||||
|
|
||||||
|
|
||||||
def MetaInfoPath(path: Path) -> MetaBase:
|
def MetaInfoPath(path: Path, custom_words: List[str] = None) -> MetaBase:
|
||||||
"""
|
"""
|
||||||
根据路径识别元数据
|
根据路径识别元数据
|
||||||
:param path: 路径
|
:param path: 路径
|
||||||
|
:param custom_words: 自定义识别词列表
|
||||||
"""
|
"""
|
||||||
# 文件元数据,不包含后缀
|
# 文件元数据,不包含后缀
|
||||||
file_meta = MetaInfo(title=path.name)
|
file_meta = MetaInfo(title=path.name, custom_words=custom_words)
|
||||||
# 上级目录元数据
|
# 上级目录元数据
|
||||||
dir_meta = MetaInfo(title=path.parent.name)
|
dir_meta = MetaInfo(title=path.parent.name, custom_words=custom_words)
|
||||||
if file_meta.type == MediaType.TV or dir_meta.type != MediaType.TV:
|
if file_meta.type == MediaType.TV or dir_meta.type != MediaType.TV:
|
||||||
# 合并元数据
|
# 合并元数据
|
||||||
file_meta.merge(dir_meta)
|
file_meta.merge(dir_meta)
|
||||||
# 上上级目录元数据
|
# 上上级目录元数据
|
||||||
root_meta = MetaInfo(title=path.parent.parent.name)
|
root_meta = MetaInfo(title=path.parent.parent.name, custom_words=custom_words)
|
||||||
if file_meta.type == MediaType.TV or root_meta.type != MediaType.TV:
|
if file_meta.type == MediaType.TV or root_meta.type != MediaType.TV:
|
||||||
# 合并元数据
|
# 合并元数据
|
||||||
file_meta.merge(root_meta)
|
file_meta.merge(root_meta)
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ class DownloadHistory(Base):
|
|||||||
media_category = Column(String)
|
media_category = Column(String)
|
||||||
# 剧集组
|
# 剧集组
|
||||||
episode_group = Column(String)
|
episode_group = Column(String)
|
||||||
|
# 自定义识别词(用于整理时应用)
|
||||||
|
custom_words = Column(String)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@db_query
|
@db_query
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
"""2.2.3
|
||||||
|
添加 downloadhistory.custom_words 字段,用于整理时应用订阅识别词
|
||||||
|
|
||||||
|
Revision ID: 58edfac72c32
|
||||||
|
Revises: 41ef1dd7467c
|
||||||
|
Create Date: 2026-01-19
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = "58edfac72c32"
|
||||||
|
down_revision = "41ef1dd7467c"
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
conn = op.get_bind()
|
||||||
|
inspector = sa.inspect(conn)
|
||||||
|
|
||||||
|
# 检查并添加 downloadhistory.custom_words
|
||||||
|
dh_columns = inspector.get_columns('downloadhistory')
|
||||||
|
if not any(c['name'] == 'custom_words' for c in dh_columns):
|
||||||
|
op.add_column('downloadhistory', sa.Column('custom_words', sa.String, nullable=True))
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
# 降级时删除字段
|
||||||
|
op.drop_column('downloadhistory', 'custom_words')
|
||||||
@@ -13,6 +13,12 @@ if __name__ == '__main__':
|
|||||||
suite.addTest(MetaInfoTest('test_emby_format_ids'))
|
suite.addTest(MetaInfoTest('test_emby_format_ids'))
|
||||||
suite.addTest(ObjectUtilsTest('test_check_method'))
|
suite.addTest(ObjectUtilsTest('test_check_method'))
|
||||||
|
|
||||||
|
# 测试自定义识别词功能
|
||||||
|
suite.addTest(MetaInfoTest('test_metainfopath_with_custom_words'))
|
||||||
|
suite.addTest(MetaInfoTest('test_metainfopath_without_custom_words'))
|
||||||
|
suite.addTest(MetaInfoTest('test_metainfopath_with_empty_custom_words'))
|
||||||
|
suite.addTest(MetaInfoTest('test_custom_words_apply_words_recording'))
|
||||||
|
|
||||||
# 测试蓝光目录识别
|
# 测试蓝光目录识别
|
||||||
suite.addTest(BluRayTest())
|
suite.addTest(BluRayTest())
|
||||||
|
|
||||||
|
|||||||
@@ -61,3 +61,38 @@ class MetaInfoTest(TestCase):
|
|||||||
meta = MetaInfoPath(Path(path_str))
|
meta = MetaInfoPath(Path(path_str))
|
||||||
self.assertEqual(meta.tmdbid, expected_tmdbid,
|
self.assertEqual(meta.tmdbid, expected_tmdbid,
|
||||||
f"路径 {path_str} 期望的tmdbid为 {expected_tmdbid},实际识别为 {meta.tmdbid}")
|
f"路径 {path_str} 期望的tmdbid为 {expected_tmdbid},实际识别为 {meta.tmdbid}")
|
||||||
|
|
||||||
|
def test_metainfopath_with_custom_words(self):
|
||||||
|
"""测试 MetaInfoPath 使用自定义识别词"""
|
||||||
|
# 测试替换词:将"测试替换"替换为空
|
||||||
|
custom_words = ["测试替换 => "]
|
||||||
|
path = Path("/movies/电影测试替换名称 (2024)/movie.mkv")
|
||||||
|
meta = MetaInfoPath(path, custom_words=custom_words)
|
||||||
|
# 验证替换生效:cn_name 不应包含"测试替换"
|
||||||
|
if meta.cn_name:
|
||||||
|
self.assertNotIn("测试替换", meta.cn_name)
|
||||||
|
|
||||||
|
def test_metainfopath_without_custom_words(self):
|
||||||
|
"""测试 MetaInfoPath 不传入自定义识别词"""
|
||||||
|
path = Path("/movies/Normal Movie (2024)/movie.mkv")
|
||||||
|
meta = MetaInfoPath(path)
|
||||||
|
# 验证正常识别,不报错
|
||||||
|
self.assertIsNotNone(meta)
|
||||||
|
|
||||||
|
def test_metainfopath_with_empty_custom_words(self):
|
||||||
|
"""测试 MetaInfoPath 传入空的自定义识别词"""
|
||||||
|
path = Path("/movies/Test Movie (2024)/movie.mkv")
|
||||||
|
meta = MetaInfoPath(path, custom_words=[])
|
||||||
|
# 验证不报错,正常识别
|
||||||
|
self.assertIsNotNone(meta)
|
||||||
|
|
||||||
|
def test_custom_words_apply_words_recording(self):
|
||||||
|
"""测试 apply_words 记录功能"""
|
||||||
|
custom_words = ["替换词 => 新词"]
|
||||||
|
title = "电影替换词.2024.mkv"
|
||||||
|
meta = MetaInfo(title=title, custom_words=custom_words)
|
||||||
|
# 验证 apply_words 属性存在
|
||||||
|
self.assertTrue(hasattr(meta, 'apply_words'))
|
||||||
|
# 如果替换词被应用,应该记录在 apply_words 中
|
||||||
|
if meta.apply_words:
|
||||||
|
self.assertIn("替换词 => 新词", meta.apply_words)
|
||||||
|
|||||||
Reference in New Issue
Block a user