fix 115 open api

This commit is contained in:
jxxghp
2025-03-24 12:04:23 +08:00
parent 4a0ecf36c7
commit d502f33041
7 changed files with 39 additions and 31 deletions
-2
View File
@@ -110,8 +110,6 @@ class ChainBase(metaclass=ABCMeta):
module_name = module_id module_name = module_id
try: try:
func = getattr(module, method) func = getattr(module, method)
# 添加日志记录类型
logger.debug(f"调用方法类型: {type(func)}")
if is_result_empty(result): if is_result_empty(result):
# 返回None,第一次执行或者需继续执行下一模块 # 返回None,第一次执行或者需继续执行下一模块
result = func(*args, **kwargs) result = func(*args, **kwargs)
+1 -1
View File
@@ -69,7 +69,7 @@ class StorageBase(metaclass=ABCMeta):
pass pass
@abstractmethod @abstractmethod
def list(self, fileitem: schemas.FileItem) -> Optional[List[schemas.FileItem]]: def list(self, fileitem: schemas.FileItem) -> List[schemas.FileItem]:
""" """
浏览文件 浏览文件
""" """
+1 -1
View File
@@ -306,7 +306,7 @@ class AliPan(StorageBase, metaclass=Singleton):
if folder: if folder:
return folder return folder
# 逐级查找和创建目录 # 逐级查找和创建目录
fileitem = schemas.FileItem(path="/") fileitem = schemas.FileItem(storage=self.schema.value, path="/")
for part in path.parts: for part in path.parts:
if part == "/": if part == "/":
continue continue
+5 -5
View File
@@ -137,7 +137,7 @@ class Alist(StorageBase, metaclass=Singleton):
page: int = 1, page: int = 1,
per_page: int = 0, per_page: int = 0,
refresh: bool = False, refresh: bool = False,
) -> Optional[List[schemas.FileItem]]: ) -> List[schemas.FileItem]:
""" """
浏览文件 浏览文件
:param fileitem: 文件项 :param fileitem: 文件项
@@ -150,7 +150,7 @@ class Alist(StorageBase, metaclass=Singleton):
item = self.get_item(Path(fileitem.path)) item = self.get_item(Path(fileitem.path))
if item: if item:
return [item] return [item]
return None return []
resp: Response = RequestUtils( resp: Response = RequestUtils(
headers=self.__get_header_with_token() headers=self.__get_header_with_token()
).post_res( ).post_res(
@@ -201,12 +201,12 @@ class Alist(StorageBase, metaclass=Singleton):
if resp is None: if resp is None:
logging.warning(f"请求获取目录 {fileitem.path} 的文件列表失败,无法连接alist服务") logging.warning(f"请求获取目录 {fileitem.path} 的文件列表失败,无法连接alist服务")
return None return []
if resp.status_code != 200: if resp.status_code != 200:
logging.warning( logging.warning(
f"请求获取目录 {fileitem.path} 的文件列表失败,状态码:{resp.status_code}" f"请求获取目录 {fileitem.path} 的文件列表失败,状态码:{resp.status_code}"
) )
return None return []
result = resp.json() result = resp.json()
@@ -214,7 +214,7 @@ class Alist(StorageBase, metaclass=Singleton):
logging.warning( logging.warning(
f'获取目录 {fileitem.path} 的文件列表失败,错误信息:{result["message"]}' f'获取目录 {fileitem.path} 的文件列表失败,错误信息:{result["message"]}'
) )
return None return []
return [ return [
schemas.FileItem( schemas.FileItem(
+1 -1
View File
@@ -65,7 +65,7 @@ class LocalStorage(StorageBase):
modify_time=path.stat().st_mtime, modify_time=path.stat().st_mtime,
) )
def list(self, fileitem: schemas.FileItem) -> Optional[List[schemas.FileItem]]: def list(self, fileitem: schemas.FileItem) -> List[schemas.FileItem]:
""" """
浏览文件 浏览文件
""" """
+2 -2
View File
@@ -98,7 +98,7 @@ class Rclone(StorageBase):
logger.error(f"rclone存储检查失败:{err}") logger.error(f"rclone存储检查失败:{err}")
return False return False
def list(self, fileitem: schemas.FileItem) -> Optional[List[schemas.FileItem]]: def list(self, fileitem: schemas.FileItem) -> List[schemas.FileItem]:
""" """
浏览文件 浏览文件
""" """
@@ -161,7 +161,7 @@ class Rclone(StorageBase):
if folder: if folder:
return folder return folder
# 逐级查找和创建目录 # 逐级查找和创建目录
fileitem = schemas.FileItem(path="/") fileitem = schemas.FileItem(storage=self.schema.value, path="/")
for part in path.parts[1:]: for part in path.parts[1:]:
dir_file = __find_dir(fileitem, part) dir_file = __find_dir(fileitem, part)
if dir_file: if dir_file:
+29 -19
View File
@@ -8,11 +8,13 @@ from typing import List, Dict, Optional, Tuple, Union
import requests import requests
from app import schemas from app import schemas
from app.api.endpoints.dashboard import storage
from app.core.config import settings from app.core.config import settings
from app.log import logger from app.log import logger
from app.modules.filemanager import StorageBase from app.modules.filemanager import StorageBase
from app.schemas.types import StorageSchema from app.schemas.types import StorageSchema
from app.utils.singleton import Singleton from app.utils.singleton import Singleton
from app.utils.string import StringUtils
class U115Pan(StorageBase, metaclass=Singleton): class U115Pan(StorageBase, metaclass=Singleton):
@@ -52,6 +54,7 @@ class U115Pan(StorageBase, metaclass=Singleton):
"Accept-Encoding": "gzip, deflate", "Accept-Encoding": "gzip, deflate",
"Content-Type": "application/x-www-form-urlencoded" "Content-Type": "application/x-www-form-urlencoded"
}) })
self.init_storage()
@property @property
def access_token(self) -> Optional[str]: def access_token(self) -> Optional[str]:
@@ -64,7 +67,7 @@ class U115Pan(StorageBase, metaclass=Singleton):
return None return None
expires_in = tokens.get("expires_in", 0) expires_in = tokens.get("expires_in", 0)
refresh_time = tokens.get("refresh_time", 0) refresh_time = tokens.get("refresh_time", 0)
if expires_in and refresh_time + expires_in >= int(time.time()): if expires_in and refresh_time + expires_in < int(time.time()):
tokens = self.__refresh_access_token(refresh_token) tokens = self.__refresh_access_token(refresh_token)
if tokens: if tokens:
self.set_config({ self.set_config({
@@ -81,7 +84,7 @@ class U115Pan(StorageBase, metaclass=Singleton):
code_verifier = secrets.token_urlsafe(96)[:128] code_verifier = secrets.token_urlsafe(96)[:128]
code_challenge = base64.urlsafe_b64encode( code_challenge = base64.urlsafe_b64encode(
hashlib.sha256(code_verifier.encode()).digest() hashlib.sha256(code_verifier.encode()).digest()
).decode().replace("=", "") ).decode()
# 请求设备码 # 请求设备码
resp = self.session.post( resp = self.session.post(
"https://passportapi.115.com/open/authDeviceCode", "https://passportapi.115.com/open/authDeviceCode",
@@ -250,35 +253,35 @@ class U115Pan(StorageBase, metaclass=Singleton):
sha1.update(chunk) sha1.update(chunk)
return sha1.hexdigest() return sha1.hexdigest()
def check_login(self) -> Optional[Dict]: def check_login(self) -> Optional[Tuple[dict, str]]:
""" """
改进的带PKCE校验的登录状态检查 改进的带PKCE校验的登录状态检查
""" """
if not self._auth_state: if not self._auth_state:
return {"status": -1, "tip": "生成二维码失败"} return {}, "生成二维码失败"
try: try:
resp = self.session.post( resp = self.session.get(
"https://passportapi.115.com/open/checkDeviceCode", "https://qrcodeapi.115.com/get/status/",
data={ params={
"uid": self._auth_state["uid"], "uid": self._auth_state["uid"],
"time": self._auth_state["time"], "time": self._auth_state["time"],
"sign": self._auth_state["sign"] "sign": self._auth_state["sign"]
} }
) )
if resp is None: if resp is None:
return {"status": -1, "tip": "网络错误"} return {}, "网络错误"
result = resp.json() result = resp.json()
if result.get("code") != 0 or not result.get("data"): if result.get("code") != 0 or not result.get("data"):
return {"status": -1, "tip": result.get("message")} return {}, result.get("message")
if result["data"]["status"] == 2: if result["data"]["status"] == 2:
tokens = self.__get_access_token() tokens = self.__get_access_token()
self.set_config({ self.set_config({
"refresh_time": int(time.time()), "refresh_time": int(time.time()),
**tokens **tokens
}) })
return {"status": result["data"]["status"], "tip": result["data"]["msg"]} return {"status": result["data"]["status"], "tip": result["data"]["msg"]}, ""
except requests.exceptions.RequestException as e: except Exception as e:
return {"status": -1, "tip": str(e)} return {}, str(e)
def init_storage(self): def init_storage(self):
""" """
@@ -294,7 +297,10 @@ class U115Pan(StorageBase, metaclass=Singleton):
""" """
if fileitem.type == "file": if fileitem.type == "file":
return [self.detail(fileitem)] item = self.detail(fileitem)
if item:
return [item]
return []
cid = self._path_to_id(fileitem.path) cid = self._path_to_id(fileitem.path)
items = [] items = []
@@ -310,8 +316,9 @@ class U115Pan(StorageBase, metaclass=Singleton):
if not resp: if not resp:
break break
for item in resp: for item in resp:
path = f"{fileitem.path}/{item['fn']}" + ("/" if item["fc"] == "0" else "") path = f"{fileitem.path}{item['fn']}" + ("/" if item["fc"] == "0" else "")
items.append(schemas.FileItem( items.append(schemas.FileItem(
storage=self.schema.value,
fileid=item["fid"], fileid=item["fid"],
name=item["fn"], name=item["fn"],
basename=Path(item["fn"]).stem, basename=Path(item["fn"]).stem,
@@ -320,11 +327,10 @@ class U115Pan(StorageBase, metaclass=Singleton):
path=path, path=path,
size=item["fs"] if item["fc"] == "1" else None, size=item["fs"] if item["fc"] == "1" else None,
modify_time=item["upt"], modify_time=item["upt"],
pickcode=item["pc"], pickcode=item["pc"]
thumbnail=item["thumb"],
)) ))
# 更新缓存 # 更新缓存
self._id_cache[path] = item["cid"] self._id_cache[path] = item["fid"]
if len(resp) < 1000: if len(resp) < 1000:
break break
@@ -350,6 +356,7 @@ class U115Pan(StorageBase, metaclass=Singleton):
# 缓存新目录 # 缓存新目录
self._id_cache[str(new_path)] = resp["file_id"] self._id_cache[str(new_path)] = resp["file_id"]
return schemas.FileItem( return schemas.FileItem(
storage=self.schema.value,
fileid=resp["file_id"], fileid=resp["file_id"],
path=str(new_path) + "/", path=str(new_path) + "/",
name=name, name=name,
@@ -388,6 +395,7 @@ class U115Pan(StorageBase, metaclass=Singleton):
# 处理秒传成功 # 处理秒传成功
if init_resp.get("status") == 2: if init_resp.get("status") == 2:
return schemas.FileItem( return schemas.FileItem(
storage=self.schema.value,
fileid=init_resp["file_id"], fileid=init_resp["file_id"],
path=str(Path(target_dir.path) / target_name), path=str(Path(target_dir.path) / target_name),
name=target_name, name=target_name,
@@ -457,6 +465,7 @@ class U115Pan(StorageBase, metaclass=Singleton):
# 构造返回结果 # 构造返回结果
return schemas.FileItem( return schemas.FileItem(
storage=self.schema.value,
fileid=init_resp.get("file_id") or self._path_to_id(str(Path(target_dir.path) / target_name)), fileid=init_resp.get("file_id") or self._path_to_id(str(Path(target_dir.path) / target_name)),
type="file", type="file",
path=str(Path(target_dir.path) / target_name), path=str(Path(target_dir.path) / target_name),
@@ -549,6 +558,7 @@ class U115Pan(StorageBase, metaclass=Singleton):
} }
) )
return schemas.FileItem( return schemas.FileItem(
storage=self.schema.value,
fileid=resp["file_id"], fileid=resp["file_id"],
path=str(path) + ("/" if resp["file_category"] == "1" else ""), path=str(path) + ("/" if resp["file_category"] == "1" else ""),
type="file" if resp["file_category"] == "1" else "dir", type="file" if resp["file_category"] == "1" else "dir",
@@ -556,7 +566,7 @@ class U115Pan(StorageBase, metaclass=Singleton):
basename=Path(resp["file_name"]).stem, basename=Path(resp["file_name"]).stem,
extension=Path(resp["file_name"]).suffix[1:], extension=Path(resp["file_name"]).suffix[1:],
pickcode=resp["pick_code"], pickcode=resp["pick_code"],
size=resp["size"] if resp["file_category"] == "1" else None, size=StringUtils.num_filesize(resp['size']) if resp["file_category"] == "1" else None,
modify_time=resp["utime"] modify_time=resp["utime"]
) )
except Exception as e: except Exception as e:
@@ -584,7 +594,7 @@ class U115Pan(StorageBase, metaclass=Singleton):
if folder: if folder:
return folder return folder
# 逐级查找和创建目录 # 逐级查找和创建目录
fileitem = schemas.FileItem(path="/") fileitem = schemas.FileItem(storage=self.schema.value, path="/")
for part in path.parts[1:]: for part in path.parts[1:]:
dir_file = __find_dir(fileitem, part) dir_file = __find_dir(fileitem, part)
if dir_file: if dir_file: