Merge pull request #5423 from jxxghp/copilot/update-category-helper-integration

This commit is contained in:
jxxghp
2026-01-26 12:35:05 +08:00
committed by GitHub
5 changed files with 81 additions and 57 deletions
+3 -3
View File
@@ -1,8 +1,8 @@
from fastapi import APIRouter, Depends from fastapi import APIRouter, Depends
from app import schemas from app import schemas
from app.chain.tmdb import TmdbChain
from app.db.models import User from app.db.models import User
from app.db.user_oper import get_current_active_superuser, get_current_active_user from app.db.user_oper import get_current_active_superuser, get_current_active_user
from app.helper.category import CategoryHelper
from app.schemas.category import CategoryConfig from app.schemas.category import CategoryConfig
router = APIRouter() router = APIRouter()
@@ -13,7 +13,7 @@ def get_category_config(_: User = Depends(get_current_active_user)):
""" """
获取分类策略配置 获取分类策略配置
""" """
config = CategoryHelper().load() config = TmdbChain().category_config()
return schemas.Response(success=True, data=config.model_dump()) return schemas.Response(success=True, data=config.model_dump())
@@ -22,7 +22,7 @@ def save_category_config(config: CategoryConfig, _: User = Depends(get_current_a
""" """
保存分类策略配置 保存分类策略配置
""" """
if CategoryHelper().save(config): if TmdbChain().save_category_config(config):
return schemas.Response(success=True, message="保存成功") return schemas.Response(success=True, message="保存成功")
else: else:
return schemas.Response(success=False, message="保存失败") return schemas.Response(success=False, message="保存失败")
+13
View File
@@ -26,6 +26,7 @@ from app.helper.service import ServiceConfigHelper
from app.log import logger from app.log import logger
from app.schemas import TransferInfo, TransferTorrent, ExistMediaInfo, DownloadingTorrent, CommingMessage, Notification, \ from app.schemas import TransferInfo, TransferTorrent, ExistMediaInfo, DownloadingTorrent, CommingMessage, Notification, \
WebhookEventInfo, TmdbEpisode, MediaPerson, FileItem, TransferDirectoryConf WebhookEventInfo, TmdbEpisode, MediaPerson, FileItem, TransferDirectoryConf
from app.schemas.category import CategoryConfig
from app.schemas.types import TorrentStatus, MediaType, MediaImageType, EventType, MessageChannel from app.schemas.types import TorrentStatus, MediaType, MediaImageType, EventType, MessageChannel
from app.utils.object import ObjectUtils from app.utils.object import ObjectUtils
@@ -1062,6 +1063,18 @@ class ChainBase(metaclass=ABCMeta):
""" """
return self.run_module("media_category") return self.run_module("media_category")
def category_config(self) -> CategoryConfig:
"""
获取分类策略配置
"""
return self.run_module("load_category_config")
def save_category_config(self, config: CategoryConfig) -> bool:
"""
保存分类策略配置
"""
return self.run_module("save_category_config", config=config)
def register_commands(self, commands: Dict[str, dict]) -> None: def register_commands(self, commands: Dict[str, dict]) -> None:
""" """
注册菜单命令 注册菜单命令
-52
View File
@@ -1,52 +0,0 @@
import yaml
from app.core.config import settings
from app.log import logger
from app.schemas.category import CategoryConfig
HEADER_COMMENTS = """####### 配置说明 #######
# 1. 该配置文件用于配置电影和电视剧的分类策略,配置后程序会按照配置的分类策略名称进行分类,配置文件采用yaml格式,需要严格附合语法规则
# 2. 配置文件中的一级分类名称:`movie`、`tv` 为固定名称不可修改,二级名称同时也是目录名称,会按先后顺序匹配,匹配后程序会按这个名称建立二级目录
# 3. 支持的分类条件:
# `original_language` 语种,具体含义参考下方字典
# `production_countries` 国家或地区(电影)、`origin_country` 国家或地区(电视剧),具体含义参考下方字典
# `genre_ids` 内容类型,具体含义参考下方字典
# `release_year` 发行年份,格式:YYYY,电影实际对应`release_date`字段,电视剧实际对应`first_air_date`字段,支持范围设定,如:`YYYY-YYYY`
# themoviedb 详情API返回的其它一级字段
# 4. 配置多项条件时需要同时满足,一个条件需要匹配多个值是使用`,`分隔
# 5. !条件值表示排除该值
"""
class CategoryHelper:
def __init__(self):
self._config_path = settings.CONFIG_PATH / 'category.yaml'
def load(self) -> CategoryConfig:
"""
加载配置
"""
config = CategoryConfig()
if not self._config_path.exists():
return config
try:
with open(self._config_path, 'r', encoding='utf-8') as f:
data = yaml.safe_load(f)
if data:
config = CategoryConfig(**data)
except Exception as e:
logger.error(f"Load category config failed: {e}")
return config
def save(self, config: CategoryConfig) -> bool:
"""
保存配置
"""
data = config.model_dump(exclude_none=True)
try:
with open(self._config_path, 'w', encoding='utf-8') as f:
f.write(HEADER_COMMENTS)
yaml.dump(data, f, allow_unicode=True, sort_keys=False, default_flow_style=False)
return True
except Exception as e:
logger.error(f"Save category config failed: {e}")
return False
+14
View File
@@ -14,10 +14,12 @@ from app.modules.themoviedb.category import CategoryHelper
from app.modules.themoviedb.scraper import TmdbScraper from app.modules.themoviedb.scraper import TmdbScraper
from app.modules.themoviedb.tmdb_cache import TmdbCache from app.modules.themoviedb.tmdb_cache import TmdbCache
from app.modules.themoviedb.tmdbapi import TmdbApi from app.modules.themoviedb.tmdbapi import TmdbApi
from app.schemas.category import CategoryConfig
from app.schemas.types import MediaType, MediaImageType, ModuleType, MediaRecognizeType from app.schemas.types import MediaType, MediaImageType, ModuleType, MediaRecognizeType
from app.utils.http import RequestUtils from app.utils.http import RequestUtils
class TheMovieDbModule(_ModuleBase): class TheMovieDbModule(_ModuleBase):
""" """
TMDB媒体信息匹配 TMDB媒体信息匹配
@@ -1290,3 +1292,15 @@ class TheMovieDbModule(_ModuleBase):
self.tmdb.clear_cache() self.tmdb.clear_cache()
self.cache.clear() self.cache.clear()
logger.info("TMDB缓存清除完成") logger.info("TMDB缓存清除完成")
def load_category_config(self) -> CategoryConfig:
"""
加载分类配置
"""
return self.category.load()
def save_category_config(self, config: CategoryConfig) -> bool:
"""
保存分类配置
"""
return self.category.save(config)
+51 -2
View File
@@ -7,8 +7,23 @@ from ruamel.yaml import CommentedMap
from app.core.config import settings from app.core.config import settings
from app.log import logger from app.log import logger
from app.schemas.category import CategoryConfig
from app.utils.singleton import WeakSingleton from app.utils.singleton import WeakSingleton
HEADER_COMMENTS = """####### 配置说明 #######
# 1. 该配置文件用于配置电影和电视剧的分类策略,配置后程序会按照配置的分类策略名称进行分类,配置文件采用yaml格式,需要严格符合语法规则
# 2. 配置文件中的一级分类名称:`movie`、`tv` 为固定名称不可修改,二级名称同时也是目录名称,会按先后顺序匹配,匹配后程序会按这个名称建立二级目录
# 3. 支持的分类条件:
# `original_language` 语种,具体含义参考下方字典
# `production_countries` 国家或地区(电影)、`origin_country` 国家或地区(电视剧),具体含义参考下方字典
# `genre_ids` 内容类型,具体含义参考下方字典
# `release_year` 发行年份,格式:YYYY,电影实际对应`release_date`字段,电视剧实际对应`first_air_date`字段,支持范围设定,如:`YYYY-YYYY`
# themoviedb 详情API返回的其它一级字段
# 4. 配置多项条件时需要同时满足,一个条件需要匹配多个值是使用`,`分隔
# 5. !条件值表示排除该值
"""
class CategoryHelper(metaclass=WeakSingleton): class CategoryHelper(metaclass=WeakSingleton):
""" """
@@ -31,8 +46,8 @@ class CategoryHelper(metaclass=WeakSingleton):
shutil.copy(settings.INNER_CONFIG_PATH / "category.yaml", self._category_path) shutil.copy(settings.INNER_CONFIG_PATH / "category.yaml", self._category_path)
with open(self._category_path, mode='r', encoding='utf-8') as f: with open(self._category_path, mode='r', encoding='utf-8') as f:
try: try:
yaml = ruamel.yaml.YAML() yaml_loader = ruamel.yaml.YAML()
self._categorys = yaml.load(f) self._categorys = yaml_loader.load(f)
except Exception as e: except Exception as e:
logger.warn(f"二级分类策略配置文件格式出现严重错误!请检查:{str(e)}") logger.warn(f"二级分类策略配置文件格式出现严重错误!请检查:{str(e)}")
self._categorys = {} self._categorys = {}
@@ -44,6 +59,40 @@ class CategoryHelper(metaclass=WeakSingleton):
self._tv_categorys = self._categorys.get('tv') self._tv_categorys = self._categorys.get('tv')
logger.info(f"已加载二级分类策略 category.yaml") logger.info(f"已加载二级分类策略 category.yaml")
def load(self) -> CategoryConfig:
"""
加载配置
"""
config = CategoryConfig()
if not self._category_path.exists():
return config
try:
with open(self._category_path, 'r', encoding='utf-8') as f:
yaml_loader = ruamel.yaml.YAML()
data = yaml_loader.load(f)
if data:
config = CategoryConfig(**data)
except Exception as e:
logger.error(f"Load category config failed: {e}")
return config
def save(self, config: CategoryConfig) -> bool:
"""
保存配置
"""
data = config.model_dump(exclude_none=True)
try:
with open(self._category_path, 'w', encoding='utf-8') as f:
f.write(HEADER_COMMENTS)
yaml_dumper = ruamel.yaml.YAML()
yaml_dumper.dump(data, f)
# 保存后重新加载配置
self.init()
return True
except Exception as e:
logger.error(f"Save category config failed: {e}")
return False
@property @property
def is_movie_category(self) -> bool: def is_movie_category(self) -> bool:
""" """