Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.v2.json
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,12 @@
"name": "Plex演职人员刮削",
"description": "实现刮削演职人员中文名称及角色。",
"labels": "Plex,刮削",
"version": "2.2",
"version": "2.3",
"icon": "https://raw.githubusercontent.com/InfinityPacer/MoviePilot-Plugins/main/icons/plexpersonmeta.png",
"author": "InfinityPacer",
"level": 1,
"history": {
"v2.3": "修复开启清理缓存后插件加载失败的问题",
"v2.2": "兼容 MoviePilot v2.13.x 的中文简繁转换接口,避免插件加载失败",
"v2.1": "修复MoviePilot缓存接口变更导致无法启动的问题",
"v2.0": "兼容MoviePilot的Redis缓存方案,需要MoviePilot v2.2.3+",
Expand Down
2 changes: 1 addition & 1 deletion plugins.v2/plexpersonmeta/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

实现刮削演职人员中文名称及角色

> 当前版本:v2.2,兼容 MoviePilot v2.13.x 的中文简繁转换接口,避免插件加载失败
> 当前版本:v2.3,修复开启清理缓存后插件加载失败的问题

- **技术难点**:Plex 的 API 实现较为复杂,特别是在处理关联演职人员的 `tagKey`,我在尝试为 `actor.tag.tagKey` 赋值时遇到了问题。如果您对此有所了解,请不吝赐教,欢迎通过在项目的 GitHub 页面新增一个 issue 与我联系,我将非常感谢您的反馈和帮助。

Expand Down
2 changes: 1 addition & 1 deletion plugins.v2/plexpersonmeta/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class PlexPersonMeta(_PluginBase):
# 插件图标
plugin_icon = "https://raw.githubusercontent.com/InfinityPacer/MoviePilot-Plugins/main/icons/plexpersonmeta.png"
# 插件版本
plugin_version = "2.2"
plugin_version = "2.3"
# 插件作者
plugin_author = "InfinityPacer"
# 作者主页
Expand Down
16 changes: 5 additions & 11 deletions plugins.v2/plexpersonmeta/scrape.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@

from app.chain.mediaserver import MediaServerChain
from app.chain.tmdb import TmdbChain
from app.core.cache import Cache
from app.core.context import MediaInfo
from app.log import logger
from app.plugins import PluginChian
from app.plugins.plexpersonmeta.helper import RatingInfo, cache_with_logging
from app.plugins.plexpersonmeta.helper import RatingInfo, cache_backend, cache_with_logging
from app.schemas import MediaPerson, ServiceInfo
from app.schemas.types import MediaType
from app.utils.zhconv import convert as zhconv_convert
Expand All @@ -36,7 +35,6 @@ def __init__(self, config: dict, event: threading.Event, chain: PluginChian,
self.service = service
self.plex = service.instance if service else None
self.libraries = libraries
self.cache_backend = Cache(maxsize=100000, ttl=60 * 60 * 24 * 3)

if not config:
return
Expand Down Expand Up @@ -837,11 +835,7 @@ def extract_key_from_url(url: str) -> Optional[str]:
return match.group(1) if match else None

@staticmethod
def clear_cache(self):
"""
清理缓存
"""
self.cache_backend.clear(region="plex_tmdb_media")
self.cache_backend.clear(region="plex_tmdb_person")
self.cache_backend.clear(region="plex_douban_media")
self.cache_backend.close()
def clear_cache():
"""清理插件用于识别结果的缓存分区。"""
for region in ("plex_tmdb_media", "plex_tmdb_person", "plex_douban_media"):
cache_backend.clear(region=region)
53 changes: 53 additions & 0 deletions tests/v2/plexpersonmeta/test_cache_scheduler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""PlexPersonMeta 缓存清理任务的调度与执行测试。"""

import importlib.util
import sys
from pathlib import Path
from types import ModuleType
from unittest.mock import MagicMock, call, patch

from apscheduler.schedulers.background import BackgroundScheduler
from app.testing import stub_modules


def _load_source_module():
"""直接加载插件源码,避免测试误用后端运行时副本。"""
source_path = Path(__file__).parents[3] / "plugins.v2" / "plexpersonmeta" / "scrape.py"
module_name = "_plexpersonmeta_source_scrape"
spec = importlib.util.spec_from_file_location(module_name, source_path)
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.exec_module(module)
return module


_pypinyin = ModuleType("pypinyin")
_pypinyin.lazy_pinyin = lambda *_args, **_kwargs: []

with stub_modules({"pypinyin": _pypinyin}):
_scrape = _load_source_module()


def test_clear_cache_can_be_registered_as_a_no_argument_job():
"""清理缓存任务必须能被 APScheduler 按无参数函数注册。"""
scheduler = BackgroundScheduler()
try:
job = scheduler.add_job(func=_scrape.ScrapeHelper.clear_cache, trigger="date")
assert job.func is _scrape.ScrapeHelper.clear_cache
finally:
scheduler.remove_all_jobs()


def test_clear_cache_clears_the_regions_used_by_cache_decorator():
"""清理操作应作用于装饰器实际使用的三个缓存分区。"""
cache_backend = MagicMock()

with patch.object(_scrape, "cache_backend", cache_backend):
_scrape.ScrapeHelper.clear_cache()

assert cache_backend.clear.call_args_list == [
call(region="plex_tmdb_media"),
call(region="plex_tmdb_person"),
call(region="plex_douban_media"),
]
cache_backend.close.assert_not_called()