mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-03-31 09:21:04 +08:00
fix: clean typing issues and refresh runtime dependencies
Align endpoint/module type hints and config reload handling while updating base Python image and package pins to improve build/runtime compatibility. Made-with: Cursor
This commit is contained in:
@@ -5,15 +5,13 @@ from fastapi import APIRouter, Depends, Body
|
||||
from app import schemas
|
||||
from app.chain.download import DownloadChain
|
||||
from app.chain.media import MediaChain
|
||||
from app.core.config import settings
|
||||
from app.core.context import MediaInfo, Context, TorrentInfo
|
||||
from app.core.event import eventmanager
|
||||
from app.core.metainfo import MetaInfo
|
||||
from app.core.security import verify_token
|
||||
from app.db.models.user import User
|
||||
from app.db.systemconfig_oper import SystemConfigOper
|
||||
from app.db.user_oper import get_current_active_user
|
||||
from app.schemas.types import ChainEventType, SystemConfigKey
|
||||
from app.schemas.types import SystemConfigKey
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ from app.db.models.user import User
|
||||
from app.db.user_oper import get_current_active_superuser_async, \
|
||||
get_current_active_user_async, get_current_active_user
|
||||
from app.db.userconfig_oper import UserConfigOper
|
||||
from app.utils.otp import OtpUtils
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@@ -253,7 +253,6 @@ class MediaChain(ChainBase, ConfigReloadMixin, metaclass=Singleton):
|
||||
"""
|
||||
流式下载图片并保存到文件
|
||||
|
||||
:param storagechain: StorageChain实例
|
||||
:param fileitem: 关联的媒体文件项
|
||||
:param path: 图片文件路径
|
||||
:param url: 图片下载URL
|
||||
|
||||
@@ -22,7 +22,6 @@ from webauthn.helpers.structs import (
|
||||
PublicKeyCredentialDescriptor,
|
||||
AuthenticatorTransport,
|
||||
UserVerificationRequirement,
|
||||
AuthenticatorAttachment,
|
||||
ResidentKeyRequirement,
|
||||
AuthenticatorSelectionCriteria
|
||||
)
|
||||
|
||||
@@ -714,7 +714,7 @@ class Emby:
|
||||
logger.error(f"连接Users/Items出错:" + str(e))
|
||||
return None
|
||||
|
||||
def get_webhook_message(self, form: any, args: dict) -> Optional[schemas.WebhookEventInfo]:
|
||||
def get_webhook_message(self, form: Any, args: dict) -> Optional[schemas.WebhookEventInfo]:
|
||||
"""
|
||||
解析Emby Webhook报文
|
||||
电影:
|
||||
|
||||
@@ -111,7 +111,7 @@ class BitptSiteUserInfo(SiteParserBase):
|
||||
def _parse_message_content(self, html_text) -> Tuple[Optional[str], Optional[str], Optional[str]]:
|
||||
pass
|
||||
|
||||
def _parse_user_torrent_seeding_info(self, html_text: str):
|
||||
def _parse_user_torrent_seeding_info(self, html_text: str, **kwargs):
|
||||
pass
|
||||
|
||||
def parse(self):
|
||||
|
||||
@@ -117,7 +117,7 @@ class ZhixingSiteUserInfo(SiteParserBase):
|
||||
def _parse_message_content(self, html_text) -> Tuple[Optional[str], Optional[str], Optional[str]]:
|
||||
pass
|
||||
|
||||
def _parse_user_torrent_seeding_info(self, html_text: str):
|
||||
def _parse_user_torrent_seeding_info(self, html_text: str, multi_page: bool = False):
|
||||
"""
|
||||
占位,避免抽象类报错
|
||||
"""
|
||||
|
||||
@@ -569,7 +569,7 @@ class Jellyfin:
|
||||
logger.error(f"连接Library/Refresh出错:" + str(e))
|
||||
return False
|
||||
|
||||
def get_webhook_message(self, body: any) -> Optional[schemas.WebhookEventInfo]:
|
||||
def get_webhook_message(self, body: Any) -> Optional[schemas.WebhookEventInfo]:
|
||||
"""
|
||||
解析Jellyfin报文
|
||||
{
|
||||
|
||||
@@ -549,7 +549,7 @@ class Plex:
|
||||
logger.error(f"获取媒体库列表出错:{str(err)}")
|
||||
return None
|
||||
|
||||
def get_webhook_message(self, form: any) -> Optional[schemas.WebhookEventInfo]:
|
||||
def get_webhook_message(self, form: Any) -> Optional[schemas.WebhookEventInfo]:
|
||||
"""
|
||||
解析Plex报文
|
||||
eventItem 字段的含义
|
||||
|
||||
@@ -409,7 +409,7 @@ class TrimeMedia:
|
||||
return lib
|
||||
return None
|
||||
|
||||
def get_webhook_message(self, body: any) -> Optional[schemas.WebhookEventInfo]:
|
||||
def get_webhook_message(self, body: Any) -> Optional[schemas.WebhookEventInfo]:
|
||||
pass
|
||||
|
||||
def get_iteminfo(self, itemid: str) -> Optional[schemas.MediaServerItem]:
|
||||
|
||||
@@ -17,34 +17,44 @@ class ConfigReloadMixin:
|
||||
def __init_subclass__(cls, **kwargs):
|
||||
super().__init_subclass__(**kwargs)
|
||||
|
||||
config_watch = getattr(cls, 'CONFIG_WATCH', None)
|
||||
config_watch = getattr(cls, "CONFIG_WATCH", None)
|
||||
if not config_watch:
|
||||
return
|
||||
|
||||
# 检查 on_config_changed 方法是否为异步
|
||||
is_async = inspect.iscoroutinefunction(cls.on_config_changed)
|
||||
|
||||
method_name = 'handle_config_changed'
|
||||
method_name = "handle_config_changed"
|
||||
|
||||
# 创建事件处理函数
|
||||
def create_handler(is_async):
|
||||
if is_async:
|
||||
|
||||
async def wrapper(self: ConfigReloadMixin, event: Event):
|
||||
if not event:
|
||||
return
|
||||
changed_keys = getattr(event.event_data, "key", set()) & config_watch
|
||||
changed_keys = (
|
||||
getattr(event.event_data, "key", set()) & config_watch
|
||||
)
|
||||
if not changed_keys:
|
||||
return
|
||||
logger.info(f"配置 {', '.join(changed_keys)} 变更,重载 {self.get_reload_name()}...")
|
||||
await self.on_config_changed()
|
||||
logger.info(
|
||||
f"配置 {', '.join(changed_keys)} 变更,重载 {self.get_reload_name()}..."
|
||||
)
|
||||
self.on_config_changed()
|
||||
else:
|
||||
|
||||
def wrapper(self: ConfigReloadMixin, event: Event):
|
||||
if not event:
|
||||
return
|
||||
changed_keys = getattr(event.event_data, "key", set()) & config_watch
|
||||
changed_keys = (
|
||||
getattr(event.event_data, "key", set()) & config_watch
|
||||
)
|
||||
if not changed_keys:
|
||||
return
|
||||
logger.info(f"配置 {', '.join(changed_keys)} 变更,重载 {self.get_reload_name()}...")
|
||||
logger.info(
|
||||
f"配置 {', '.join(changed_keys)} 变更,重载 {self.get_reload_name()}..."
|
||||
)
|
||||
self.on_config_changed()
|
||||
|
||||
return wrapper
|
||||
@@ -52,7 +62,7 @@ class ConfigReloadMixin:
|
||||
# 创建并设置处理函数
|
||||
handler = create_handler(is_async)
|
||||
handler.__module__ = cls.__module__
|
||||
handler.__qualname__ = f'{cls.__name__}.{method_name}'
|
||||
handler.__qualname__ = f"{cls.__name__}.{method_name}"
|
||||
setattr(cls, method_name, handler)
|
||||
# 添加为事件处理器
|
||||
eventmanager.add_event_listener(EventType.ConfigChanged, handler)
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
from typing import Tuple
|
||||
|
||||
import pyotp
|
||||
|
||||
|
||||
class OtpUtils:
|
||||
@staticmethod
|
||||
def generate_secret_key(username: str) -> (str, str):
|
||||
def generate_secret_key(username: str) -> Tuple[str, str]:
|
||||
try:
|
||||
secret = pyotp.random_base32()
|
||||
uri = pyotp.totp.TOTP(secret).provisioning_uri(name='MoviePilot',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM python:3.12.8-slim-bookworm AS base
|
||||
FROM python:3.12.13-slim-bookworm AS base
|
||||
|
||||
|
||||
# 准备软件包
|
||||
@@ -68,7 +68,7 @@ WORKDIR /app
|
||||
COPY requirements.in requirements.in
|
||||
RUN python3 -m venv ${VENV_PATH} \
|
||||
&& pip install --upgrade "pip<25.0" \
|
||||
&& pip install "Cython" "pip-tools<7.5" \
|
||||
&& pip install "Cython~=3.1.2" "pip-tools<7.5" \
|
||||
&& pip-compile requirements.in \
|
||||
&& pip install -r requirements.txt
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ python-multipart~=0.0.9
|
||||
aiofiles~=24.1.0
|
||||
aioshutil~=1.5
|
||||
alembic~=1.16.2
|
||||
anyio~=4.10.0
|
||||
bcrypt~=4.0.1
|
||||
regex~=2024.11.6
|
||||
cn2an~=0.5.19
|
||||
@@ -22,6 +23,7 @@ urllib3~=2.5.0
|
||||
lxml~=6.0.0
|
||||
pyquery~=2.0.1
|
||||
ruamel.yaml~=0.18.14
|
||||
PyYAML~=6.0.2
|
||||
APScheduler~=3.11.0
|
||||
cryptography~=45.0.4
|
||||
pytz~=2025.2
|
||||
@@ -31,10 +33,8 @@ plexapi~=4.17.0
|
||||
transmission-rpc~=4.3.0
|
||||
Jinja2~=3.1.6
|
||||
pyparsing~=3.2.3
|
||||
func_timeout==4.3.5
|
||||
bs4~=0.0.2
|
||||
beautifulsoup4~=4.13.4
|
||||
pillow~=11.2.1
|
||||
pillow~=12.1.1
|
||||
pillow-avif-plugin~=1.5.2
|
||||
pyTelegramBotAPI~=4.27.0
|
||||
telegramify-markdown~=0.5.2
|
||||
@@ -49,24 +49,18 @@ starlette~=0.46.2
|
||||
PyVirtualDisplay~=3.0
|
||||
psutil~=7.0.0
|
||||
python-dotenv~=1.1.1
|
||||
python-hosts~=1.1.2
|
||||
watchdog~=6.0.0
|
||||
watchfiles~=1.1.0
|
||||
cacheout~=0.16.0
|
||||
click~=8.2.1
|
||||
requests-cache~=1.2.1
|
||||
parse~=1.20.2
|
||||
docker~=7.1.0
|
||||
pywin32==310; platform_system == "Windows"
|
||||
cachetools~=6.1.0
|
||||
fast-bencode~=1.1.7
|
||||
pystray~=0.19.5
|
||||
pyotp~=2.9.0
|
||||
webauthn~=2.7.0
|
||||
Pinyin2Hanzi~=0.1.1
|
||||
pywebpush~=2.0.3
|
||||
aiopathlib~=0.6.0
|
||||
asynctempfile~=0.5.0
|
||||
aiosqlite~=0.21.0
|
||||
psycopg2-binary~=2.9.10
|
||||
asyncpg~=0.30.0
|
||||
@@ -88,8 +82,8 @@ langchain-community~=0.4.1
|
||||
langchain-openai~=1.1.11
|
||||
langchain-google-genai~=4.2.1
|
||||
langchain-deepseek~=1.0.1
|
||||
langchain-experimental~=0.4.1
|
||||
langgraph~=1.1.3
|
||||
openai~=2.29.0
|
||||
google-genai~=1.68.0
|
||||
ddgs~=9.10.0
|
||||
websocket-client~=1.8.0
|
||||
|
||||
Reference in New Issue
Block a user