From 4f806db8b7b193857c1bace25c8cbfd999f8ed28 Mon Sep 17 00:00:00 2001 From: Attente <19653207+wikrin@users.noreply.github.com> Date: Tue, 11 Nov 2025 10:44:45 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=8F=98=E6=9B=B4?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E4=B8=8B=E8=BD=BD=E5=99=A8=E4=B8=8D=E7=94=9F?= =?UTF-8?q?=E6=95=88=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 配置模块迁移到 `SettingsConfigDict` 以支持 Pydantic v2 的配置方式 - 在 `MediaInfo` 中新增 `release_dates` 字段,用于存储多地区发行日期信息 - 修改 `MetaVideo` 类中的 token 传递逻辑,以修复搜索站点资源序列化错误的问题 --- app/command.py | 2 +- app/core/config.py | 6 +++--- app/core/context.py | 14 ++++++++++++++ app/core/meta/metavideo.py | 25 ++++++++++++------------- app/modules/__init__.py | 19 +++++++++++++++++++ app/schemas/context.py | 2 ++ 6 files changed, 51 insertions(+), 17 deletions(-) diff --git a/app/command.py b/app/command.py index c403e38e..8e6a61f3 100644 --- a/app/command.py +++ b/app/command.py @@ -215,7 +215,7 @@ class Command(metaclass=Singleton): except Exception as e: logger.error(f"Error occurred during command initialization in background: {e}", exc_info=True) - def __trigger_register_commands_event(self) -> (Optional[Event], dict): + def __trigger_register_commands_event(self) -> tuple[Optional[Event], dict]: """ 触发事件,允许调整命令数据 """ diff --git a/app/core/config.py b/app/core/config.py index deac0a70..e05a2c54 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -12,7 +12,7 @@ from urllib.parse import urlparse from dotenv import set_key from pydantic import BaseModel, Field, ConfigDict, model_validator -from pydantic_settings import BaseSettings +from pydantic_settings import BaseSettings, SettingsConfigDict from app.log import logger, log_settings, LogConfigModel from app.schemas import MediaType @@ -438,10 +438,10 @@ class Settings(BaseSettings, ConfigModel, LogConfigModel): 系统配置类 """ - model_config = ConfigDict( + model_config = SettingsConfigDict( case_sensitive=True, env_file=SystemUtils.get_env_path(), - env_file_encoding="utf-8" + env_file_encoding="utf-8", ) def __init__(self, **kwargs): diff --git a/app/core/context.py b/app/core/context.py index c0e3e8b8..b2a62711 100644 --- a/app/core/context.py +++ b/app/core/context.py @@ -250,6 +250,8 @@ class MediaInfo: production_countries: list = field(default_factory=list) # 语种 spoken_languages: list = field(default_factory=list) + # 所有发行日期 + release_dates: list = field(default_factory=list) # 状态 status: str = None # 标签 @@ -433,6 +435,18 @@ class MediaInfo: if self.release_date: # 年份 self.year = self.release_date[:4] + # 所有发行日期 + self.release_dates = [ + { + "date": release_date.get("release_date"), + "iso_code": result.get("iso_3166_1"), + "note": release_date.get("note"), + "type": release_date.get("type"), + } + for result in info.get("release_dates", {}).get("results", []) + for release_date in result.get("release_dates", []) + if release_date.get("release_date") + ] else: # 电视剧 self.title = info.get('name') diff --git a/app/core/meta/metavideo.py b/app/core/meta/metavideo.py index 11fcf7ad..c612cd74 100644 --- a/app/core/meta/metavideo.py +++ b/app/core/meta/metavideo.py @@ -94,7 +94,6 @@ class MetaVideo(MetaBase): title = re.sub(r'\d{4}[\s._-]\d{1,2}[\s._-]\d{1,2}', "", title) # 拆分tokens tokens = Tokens(title) - self.tokens = tokens # 实例化StreamingPlatforms对象 streaming_platforms = StreamingPlatforms() # 解析名称、年份、季、集、资源类型、分辨率等 @@ -102,7 +101,7 @@ class MetaVideo(MetaBase): while token: self._index += 1 # 更新当前处理的token索引 # Part - self.__init_part(token) + self.__init_part(token, tokens) # 标题 if self._continue_flag: self.__init_name(token) @@ -123,7 +122,7 @@ class MetaVideo(MetaBase): self.__init_resource_type(token) # 流媒体平台 if self._continue_flag: - self.__init_web_source(token, streaming_platforms) + self.__init_web_source(token, tokens, streaming_platforms) # 视频编码 if self._continue_flag: self.__init_video_encode(token) @@ -311,7 +310,7 @@ class MetaVideo(MetaBase): self.en_name = token self._last_token_type = "enname" - def __init_part(self, token: str): + def __init_part(self, token: str, tokens: Tokens): """ 识别Part """ @@ -327,12 +326,12 @@ class MetaVideo(MetaBase): if re_res: if not self.part: self.part = re_res.group(1) - nextv = self.tokens.cur() + nextv = tokens.cur() if nextv \ and ((nextv.isdigit() and (len(nextv) == 1 or len(nextv) == 2 and nextv.startswith('0'))) or nextv.upper() in ['A', 'B', 'C', 'I', 'II', 'III']): self.part = "%s%s" % (self.part, nextv) - self.tokens.get_next() + tokens.get_next() self._last_token_type = "part" self._continue_flag = False # self._stop_name_flag = False @@ -582,7 +581,7 @@ class MetaVideo(MetaBase): self._effect.append(effect) self._last_token = effect.upper() - def __init_web_source(self, token: str, streaming_platforms: StreamingPlatforms): + def __init_web_source(self, token: str, tokens: Tokens, streaming_platforms: StreamingPlatforms): """ 识别流媒体平台 """ @@ -594,10 +593,10 @@ class MetaVideo(MetaBase): prev_token = None prev_idx = self._index - 2 - if 0 <= prev_idx < len(self.tokens.tokens): - prev_token = self.tokens.tokens[prev_idx] + if 0 <= prev_idx < len(tokens.tokens): + prev_token = tokens.tokens[prev_idx] - next_token = self.tokens.peek() + next_token = tokens.peek() if streaming_platforms.is_streaming_platform(token): platform_name = streaming_platforms.get_streaming_platform_name(token) @@ -616,7 +615,7 @@ class MetaVideo(MetaBase): platform_name = streaming_platforms.get_streaming_platform_name(combined_token) query_range = 2 if is_next: - self.tokens.get_next() + tokens.get_next() break if not platform_name: @@ -626,8 +625,8 @@ class MetaVideo(MetaBase): match_start_idx = self._index - query_range match_end_idx = self._index - 1 start_index = max(0, match_start_idx - query_range) - end_index = min(len(self.tokens.tokens), match_end_idx + 1 + query_range) - tokens_to_check = self.tokens.tokens[start_index:end_index] + end_index = min(len(tokens.tokens), match_end_idx + 1 + query_range) + tokens_to_check = tokens.tokens[start_index:end_index] if any(tok and tok.upper() in web_tokens for tok in tokens_to_check): self.web_source = platform_name diff --git a/app/modules/__init__.py b/app/modules/__init__.py index 44ee1c62..c51a9c05 100644 --- a/app/modules/__init__.py +++ b/app/modules/__init__.py @@ -232,6 +232,19 @@ class _DownloaderBase(ServiceBase[TService, DownloaderConf]): super().__init__() self._default_config_name: Optional[str] = None + def init_service(self, service_name: str, + service_type: Optional[Union[Type[TService], Callable[..., TService]]] = None): + """ + 初始化服务,获取配置并实例化对应服务 + + :param service_name: 服务名称,作为配置匹配的依据 + :param service_type: 服务的类型,可以是类类型(Type[TService])、工厂函数(Callable)或 None 来跳过实例化 + """ + # 重置默认配置名称 + self.reset_default_config_name() + # 初始化服务 + super().init_service(service_name, service_type) + def get_default_config_name(self) -> Optional[str]: """ 获取默认服务配置的名称 @@ -263,6 +276,12 @@ class _DownloaderBase(ServiceBase[TService, DownloaderConf]): return {} return {conf.name: conf for conf in configs if conf.type == self._service_name and conf.enabled} + def reset_default_config_name(self): + """ + 重置默认配置名称 + """ + self._default_config_name = None + class _MediaServerBase(ServiceBase[TService, MediaServerConf]): """ diff --git a/app/schemas/context.py b/app/schemas/context.py index f94d5ff4..cf8516a1 100644 --- a/app/schemas/context.py +++ b/app/schemas/context.py @@ -158,6 +158,8 @@ class MediaInfo(BaseModel): production_countries: Optional[list] = Field(default_factory=list) # 语种 spoken_languages: Optional[list] = Field(default_factory=list) + # 所有发行日期 + release_dates: list = Field(default_factory=list) # 状态 status: Optional[str] = None # 标签