mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-03-20 03:57:30 +08:00
fix 扫码逻辑与底层模块解耦
This commit is contained in:
@@ -16,6 +16,13 @@ class StorageBase(metaclass=ABCMeta):
|
||||
def __init__(self):
|
||||
self.storagehelper = StorageHelper()
|
||||
|
||||
@abstractmethod
|
||||
def init_storage(self):
|
||||
"""
|
||||
初始化
|
||||
"""
|
||||
pass
|
||||
|
||||
def generate_qrcode(self, *args, **kwargs) -> Optional[Tuple[dict, str]]:
|
||||
pass
|
||||
|
||||
@@ -40,6 +47,7 @@ class StorageBase(metaclass=ABCMeta):
|
||||
设置配置
|
||||
"""
|
||||
self.storagehelper.set_storage(self.schema.value, conf)
|
||||
self.init_storage()
|
||||
|
||||
def support_transtype(self) -> dict:
|
||||
"""
|
||||
|
||||
@@ -16,10 +16,11 @@ from app.schemas.types import StorageSchema
|
||||
from app.utils.http import RequestUtils
|
||||
from aligo import Aligo, BaseFile
|
||||
|
||||
from app.utils.singleton import Singleton
|
||||
from app.utils.string import StringUtils
|
||||
|
||||
|
||||
class AliPan(StorageBase):
|
||||
class AliPan(StorageBase, metaclass=Singleton):
|
||||
"""
|
||||
阿里云相关操作
|
||||
"""
|
||||
@@ -54,16 +55,21 @@ class AliPan(StorageBase):
|
||||
except FileNotFoundError:
|
||||
logger.debug('未发现 aria2c')
|
||||
self._has_aria2c = False
|
||||
self.init_storage()
|
||||
|
||||
self.__init_aligo()
|
||||
|
||||
def __init_aligo(self):
|
||||
def init_storage(self):
|
||||
"""
|
||||
初始化 aligo
|
||||
"""
|
||||
def show_qrcode(qr_link: str):
|
||||
"""
|
||||
显示二维码
|
||||
"""
|
||||
logger.info(f"请用阿里云盘 App 扫码登录:{qr_link}")
|
||||
|
||||
refresh_token = self.__auth_params.get("refreshToken")
|
||||
if refresh_token:
|
||||
self.aligo = Aligo(refresh_token=refresh_token, use_aria2=self._has_aria2c,
|
||||
self.aligo = Aligo(refresh_token=refresh_token, show=show_qrcode, use_aria2=self._has_aria2c,
|
||||
name="MoviePilot V2", level=logging.ERROR)
|
||||
|
||||
@property
|
||||
@@ -160,7 +166,7 @@ class AliPan(StorageBase):
|
||||
})
|
||||
self.__update_params(data)
|
||||
self.__update_drives()
|
||||
self.__init_aligo()
|
||||
self.init_storage()
|
||||
except Exception as e:
|
||||
return {}, f"bizExt 解码失败:{str(e)}"
|
||||
return data, ""
|
||||
@@ -180,12 +186,16 @@ class AliPan(StorageBase):
|
||||
"""
|
||||
获取用户信息(drive_id等)
|
||||
"""
|
||||
if not self.aligo:
|
||||
return {}
|
||||
return self.aligo.get_user()
|
||||
|
||||
def __update_drives(self):
|
||||
"""
|
||||
更新用户存储根目录
|
||||
"""
|
||||
if not self.aligo:
|
||||
return
|
||||
drivers = self.aligo.list_my_drives()
|
||||
for driver in drivers:
|
||||
if driver.category == "resource":
|
||||
|
||||
@@ -34,6 +34,12 @@ class Alist(StorageBase):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def init_storage(self):
|
||||
"""
|
||||
初始化
|
||||
"""
|
||||
pass
|
||||
|
||||
@property
|
||||
def __get_base_url(self) -> str:
|
||||
"""
|
||||
|
||||
@@ -25,6 +25,12 @@ class LocalStorage(StorageBase):
|
||||
"softlink": "软链接"
|
||||
}
|
||||
|
||||
def init_storage(self):
|
||||
"""
|
||||
初始化
|
||||
"""
|
||||
pass
|
||||
|
||||
def check(self) -> bool:
|
||||
"""
|
||||
检查存储是否可用
|
||||
|
||||
@@ -27,6 +27,12 @@ class Rclone(StorageBase):
|
||||
"copy": "复制"
|
||||
}
|
||||
|
||||
def init_storage(self):
|
||||
"""
|
||||
初始化
|
||||
"""
|
||||
pass
|
||||
|
||||
def set_config(self, conf: dict):
|
||||
"""
|
||||
设置配置
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
from pathlib import Path
|
||||
from typing import Optional, Tuple, List
|
||||
|
||||
from p115 import P115Client, P115FileSystem, P115Path
|
||||
from p115 import P115Client, P115Path
|
||||
|
||||
from app import schemas
|
||||
from app.core.config import settings
|
||||
from app.log import logger
|
||||
from app.modules.filemanager.storages import StorageBase
|
||||
from app.schemas.types import StorageSchema
|
||||
from app.utils.http import RequestUtils
|
||||
from app.utils.singleton import Singleton
|
||||
|
||||
|
||||
@@ -25,18 +26,29 @@ class U115Pan(StorageBase, metaclass=Singleton):
|
||||
"copy": "复制"
|
||||
}
|
||||
|
||||
# 115二维码登录地址
|
||||
qrcode_url = "https://qrcodeapi.115.com/api/1.0/web/1.0/token/"
|
||||
# 115登录状态检查
|
||||
login_check_url = "https://qrcodeapi.115.com/get/status/"
|
||||
# 115登录完成 alipaymini
|
||||
login_done_api = f"https://passportapi.115.com/app/1.0/alipaymini/1.0/login/qrcode/"
|
||||
|
||||
client: P115Client = None
|
||||
fs: P115FileSystem = None
|
||||
session_info: dict = None
|
||||
|
||||
def __init_cloud(self, force: bool = False) -> bool:
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.init_storage()
|
||||
|
||||
def init_storage(self) -> bool:
|
||||
"""
|
||||
初始化Cloud
|
||||
"""
|
||||
if not self.__credential:
|
||||
return False
|
||||
try:
|
||||
if not self.client or not self.client.cookies or force:
|
||||
self.client = P115Client(self.__credential, app="alipaymini")
|
||||
self.fs = P115FileSystem(self.client)
|
||||
self.client = P115Client(self.__credential, app="alipaymini",
|
||||
check_for_relogin=True, console_qrcode=False)
|
||||
except Exception as err:
|
||||
logger.error(f"115连接失败,请重新登录:{str(err)}")
|
||||
self.__clear_credential()
|
||||
@@ -71,10 +83,9 @@ class U115Pan(StorageBase, metaclass=Singleton):
|
||||
"""
|
||||
生成二维码
|
||||
"""
|
||||
self.__init_cloud()
|
||||
try:
|
||||
resp = self.client.login_qrcode_token()
|
||||
self.session_info = resp["data"]
|
||||
res = RequestUtils(timeout=10).get_res(self.qrcode_url)
|
||||
if res:
|
||||
self.session_info = res.json().get("data")
|
||||
qrcode_content = self.session_info.pop("qrcode")
|
||||
if not qrcode_content:
|
||||
logger.warn("115生成二维码失败:未获取到二维码数据!")
|
||||
@@ -82,9 +93,9 @@ class U115Pan(StorageBase, metaclass=Singleton):
|
||||
return {
|
||||
"codeContent": qrcode_content
|
||||
}, ""
|
||||
except Exception as e:
|
||||
logger.warn(f"115生成二维码失败:{str(e)}")
|
||||
return {}, f"115生成二维码失败:{str(e)}"
|
||||
elif res is not None:
|
||||
return {}, f"115生成二维码失败:{res.status_code} - {res.reason}"
|
||||
return {}, f"115生成二维码失败:无法连接!"
|
||||
|
||||
def check_login(self) -> Optional[Tuple[dict, str]]:
|
||||
"""
|
||||
@@ -93,8 +104,11 @@ class U115Pan(StorageBase, metaclass=Singleton):
|
||||
if not self.session_info:
|
||||
return {}, "请先生成二维码!"
|
||||
try:
|
||||
resp = self.client.login_qrcode_scan_status(self.session_info)
|
||||
match resp["data"].get("status"):
|
||||
resp = RequestUtils(timeout=10).get_res(self.login_check_url, params=self.session_info)
|
||||
if not resp:
|
||||
return {}, "115登录确认失败:无法连接!"
|
||||
result = resp.json()
|
||||
match result["data"].get("status"):
|
||||
case 0:
|
||||
result = {
|
||||
"status": 0,
|
||||
@@ -107,15 +121,18 @@ class U115Pan(StorageBase, metaclass=Singleton):
|
||||
}
|
||||
case 2:
|
||||
# 确认完成,保存认证信息
|
||||
resp = self.client.login_qrcode_scan_result(uid=self.session_info.get("uid"),
|
||||
app="alipaymini")
|
||||
resp = RequestUtils(timeout=10).post_res(self.login_done_api,
|
||||
data={"account": self.session_info.get("uid")})
|
||||
if not resp:
|
||||
return {}, "115登录确认失败:无法连接!"
|
||||
if resp:
|
||||
# 保存认证信息
|
||||
cookie_dict = resp["data"]["cookie"]
|
||||
result = resp.json()
|
||||
cookie_dict = result["data"]["cookie"]
|
||||
cookie_str = "; ".join([f"{k}={v}" for k, v in cookie_dict.items()])
|
||||
cookie_dict.update({"cookie": cookie_str})
|
||||
self.__save_credential(cookie_dict)
|
||||
self.__init_cloud(force=True)
|
||||
self.init_storage()
|
||||
result = {
|
||||
"status": 2,
|
||||
"tip": "登录成功!"
|
||||
@@ -143,10 +160,10 @@ class U115Pan(StorageBase, metaclass=Singleton):
|
||||
"""
|
||||
获取存储空间
|
||||
"""
|
||||
if not self.__init_cloud():
|
||||
if not self.client:
|
||||
return None
|
||||
try:
|
||||
usage = self.fs.space_summury()
|
||||
usage = self.client.fs.space_summury()
|
||||
if usage:
|
||||
return usage['rt_space_info']['all_total']['size'], usage['rt_space_info']['all_remain']['size']
|
||||
except Exception as e:
|
||||
@@ -163,12 +180,12 @@ class U115Pan(StorageBase, metaclass=Singleton):
|
||||
"""
|
||||
浏览文件
|
||||
"""
|
||||
if not self.__init_cloud():
|
||||
if not self.client:
|
||||
return []
|
||||
try:
|
||||
if fileitem.type == "file":
|
||||
return [fileitem]
|
||||
items: List[P115Path] = self.fs.list(fileitem.path)
|
||||
items: List[P115Path] = self.client.fs.list(fileitem.path)
|
||||
return [schemas.FileItem(
|
||||
storage=self.schema.value,
|
||||
type="dir" if item.is_dir() else "file",
|
||||
@@ -187,10 +204,10 @@ class U115Pan(StorageBase, metaclass=Singleton):
|
||||
"""
|
||||
创建目录
|
||||
"""
|
||||
if not self.__init_cloud():
|
||||
if not self.client:
|
||||
return None
|
||||
try:
|
||||
result = self.fs.makedirs(Path(fileitem.path) / name, exist_ok=True)
|
||||
result = self.client.fs.makedirs(Path(fileitem.path) / name, exist_ok=True)
|
||||
if result:
|
||||
return schemas.FileItem(
|
||||
storage=self.schema.value,
|
||||
@@ -208,10 +225,10 @@ class U115Pan(StorageBase, metaclass=Singleton):
|
||||
"""
|
||||
根据文件路程获取目录,不存在则创建
|
||||
"""
|
||||
if not self.__init_cloud():
|
||||
if not self.client:
|
||||
return None
|
||||
try:
|
||||
result = self.fs.makedirs(path, exist_ok=True)
|
||||
result = self.client.fs.makedirs(path, exist_ok=True)
|
||||
if result:
|
||||
return schemas.FileItem(
|
||||
storage=self.schema.value,
|
||||
@@ -229,11 +246,11 @@ class U115Pan(StorageBase, metaclass=Singleton):
|
||||
"""
|
||||
获取文件或目录,不存在返回None
|
||||
"""
|
||||
if not self.__init_cloud():
|
||||
if not self.client:
|
||||
return None
|
||||
try:
|
||||
try:
|
||||
item = self.fs.attr(path)
|
||||
item = self.client.fs.attr(path)
|
||||
except FileNotFoundError:
|
||||
return None
|
||||
if item:
|
||||
@@ -255,11 +272,11 @@ class U115Pan(StorageBase, metaclass=Singleton):
|
||||
"""
|
||||
获取文件详情
|
||||
"""
|
||||
if not self.__init_cloud():
|
||||
if not self.client:
|
||||
return None
|
||||
try:
|
||||
try:
|
||||
item = self.fs.attr(fileitem.path)
|
||||
item = self.client.fs.attr(fileitem.path)
|
||||
except FileNotFoundError:
|
||||
return None
|
||||
if item:
|
||||
@@ -281,10 +298,10 @@ class U115Pan(StorageBase, metaclass=Singleton):
|
||||
"""
|
||||
删除文件
|
||||
"""
|
||||
if not self.__init_cloud():
|
||||
if not self.client:
|
||||
return False
|
||||
try:
|
||||
self.fs.remove(fileitem.path)
|
||||
self.client.fs.remove(fileitem.path)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"115删除文件失败:{str(e)}")
|
||||
@@ -294,10 +311,10 @@ class U115Pan(StorageBase, metaclass=Singleton):
|
||||
"""
|
||||
重命名文件
|
||||
"""
|
||||
if not self.__init_cloud():
|
||||
if not self.client:
|
||||
return False
|
||||
try:
|
||||
self.fs.rename(fileitem.path, Path(fileitem.path).with_name(name))
|
||||
self.client.fs.rename(fileitem.path, Path(fileitem.path).with_name(name))
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"115重命名文件失败:{str(e)}")
|
||||
@@ -307,11 +324,11 @@ class U115Pan(StorageBase, metaclass=Singleton):
|
||||
"""
|
||||
获取下载链接
|
||||
"""
|
||||
if not self.__init_cloud():
|
||||
if not self.client:
|
||||
return None
|
||||
local_file = (path or settings.TEMP_PATH) / fileitem.name
|
||||
try:
|
||||
task = self.fs.download(fileitem.path, file=local_file)
|
||||
task = self.client.fs.download(fileitem.path, file=local_file)
|
||||
if task:
|
||||
return local_file
|
||||
except Exception as e:
|
||||
@@ -322,12 +339,12 @@ class U115Pan(StorageBase, metaclass=Singleton):
|
||||
"""
|
||||
上传文件
|
||||
"""
|
||||
if not self.__init_cloud():
|
||||
if not self.client:
|
||||
return None
|
||||
try:
|
||||
new_path = Path(fileitem.path) / (new_name or path.name)
|
||||
with open(path, "rb") as f:
|
||||
result = self.fs.upload(f, new_path)
|
||||
result = self.client.fs.upload(f, new_path)
|
||||
if result:
|
||||
return schemas.FileItem(
|
||||
storage=self.schema.value,
|
||||
@@ -347,10 +364,10 @@ class U115Pan(StorageBase, metaclass=Singleton):
|
||||
"""
|
||||
移动文件
|
||||
"""
|
||||
if not self.__init_cloud():
|
||||
if not self.client:
|
||||
return False
|
||||
try:
|
||||
self.fs.move(fileitem.path, target.path)
|
||||
self.client.fs.move(fileitem.path, target.path)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"115移动文件失败:{str(e)}")
|
||||
@@ -360,10 +377,10 @@ class U115Pan(StorageBase, metaclass=Singleton):
|
||||
"""
|
||||
复制文件
|
||||
"""
|
||||
if not self.__init_cloud():
|
||||
if not self.client:
|
||||
return False
|
||||
try:
|
||||
self.fs.copy(fileitem.path, target_file)
|
||||
self.client.fs.copy(fileitem.path, target_file)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.error(f"115复制文件失败:{str(e)}")
|
||||
|
||||
Reference in New Issue
Block a user