Python/utils/cloudreve.py

129 lines
4.6 KiB
Python

# -*- coding: utf-8 -*-
"""
封装 Cloudreve 客户端
"""
from typing import Generator
from urllib.parse import quote
from authenticator import Authenticator
from request import Request
class Cloudreve:
"""Cloudreve 客户端"""
def __init__(self):
# 实例化认证器
self.authenticator = Authenticator()
# 实例化请求客户端
self.http_client = Request()
def _get_upload_session(self, uri: str, size: int) -> str:
"""
获取上传会话标识
:param uri: 统一资源标识符
:param size: 文件大小
:return: 上传会话标识
"""
response = self.http_client.put(
url=f"https://cloudreve.liubiren.cloud/api/v4/file/upload",
headers={
"Authorization": f"Bearer {self.authenticator.get_token(servicer="cloudreve")}",
"Content-Type": "application/json; charset=utf-8",
},
json={
"uri": quote(string=uri, safe=":/?&="), # 编码统一资源标识
"size": size,
"policy_id": "zpHb", # https://cloudreve.liubiren.cloud/api/v4/file?uri=cloudreve://my/转直链 可查看该文件夹储存策略
},
)
# 若非响应成功则抛出异常
if not response["code"] == 0:
raise RuntimeError("创建上传会话发生异常")
return response["data"]["session_id"]
def _upload_file_chunk(self, session_id: str, index: int, chunk: bytes) -> None:
"""
上传文件块
:param session_id: 上传会话标识
:param index: 文件块索引
:param chunk: 文件块数据
:return: None
"""
response = self.http_client.post(
url=f"https://cloudreve.liubiren.cloud/api/v4/file/upload/{session_id}/{index}",
headers={
"Authorization": f"Bearer {self.authenticator.get_token(servicer="cloudreve")}",
"Content-Type": "application/octet-stream",
"Content-Length": str(len(chunk)),
},
data=chunk,
)
if not response["code"] == 0:
raise RuntimeError("上传文件块发生异常")
def _upload_file(self, uri: str, size: int, generator: Generator) -> None:
"""
上传文件
:param uri: 统一资源标识符
:param size: 文件大小
:param generator: 文件块生成器
:return: None
"""
# 获取上传会话标识
session_id = self._get_upload_session(uri=uri, size=size)
for index, chunk in enumerate(generator):
# 上传文件块
self._upload_file_chunk(session_id=session_id, index=index, chunk=chunk)
def _create_direct_link(self, uri: str) -> str:
"""
创建直链
:param uri: 统一资源标识符
:return: 直链
"""
response = self.http_client.put(
url="https://cloudreve.liubiren.cloud/api/v4/file/source",
headers={
"Authorization": f"Bearer {self.authenticator.get_token(servicer="cloudreve")}",
"Content-Type": "application/json; charset=utf-8",
},
json={
"uris": [quote(string=uri, safe=":/?&=")], # 编码统一资源标识
},
)
if not response["code"] == 0:
raise RuntimeError("获取直链发生异常")
return response["data"][0]["link"]
def get_direct_link(self, uri: str, size: int, generator: Generator) -> str:
"""
获取直链
:param uri: 统一资源标识符
:return: 直链
"""
response = self.http_client.get(
url=f"https://cloudreve.liubiren.cloud/api/v4/file/info",
headers={
"Authorization": f"Bearer {self.authenticator.get_token(servicer="cloudreve")}",
"Content-Type": "application/json; charset=utf-8",
},
params={
"uri": quote(string=uri, safe=":/?&="), # 编码统一资源标识
"extended": "true", # 获取文件扩展信息
},
)
# 若文件已存在则返回直链,否则上传文件并创建直连
if response["code"] == 0:
return response["data"]["extended_info"]["direct_links"][0]["url"]
# 上传文件
self._upload_file(
generator=generator,
uri=uri,
size=size,
)
# 创建直连
direct_link = self._create_direct_link(uri=uri)
return direct_link