mirror of
https://github.com/ctwj/urldb.git
synced 2025-11-25 03:15:04 +08:00
update: 自动转存
This commit is contained in:
@@ -344,36 +344,37 @@ func (x *XunleiPanService) Transfer(shareID string) (*TransferResult, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return ErrorResult(fmt.Sprintf("获取分享详情失败: %v", err)), nil
|
return ErrorResult(fmt.Sprintf("获取分享详情失败: %v", err)), nil
|
||||||
}
|
}
|
||||||
|
if shareDetail["share_status"].(string) != "OK" {
|
||||||
|
return ErrorResult(fmt.Sprintf("获取分享详情失败: %v", "分享状态异常")), nil
|
||||||
|
}
|
||||||
|
if shareDetail["file_num"].(string) == "0" {
|
||||||
|
return ErrorResult(fmt.Sprintf("获取分享详情失败: %v", "文件列表为空")), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
parent_id := "" // 默认存储路径
|
||||||
|
|
||||||
// 检查是否为检验模式
|
// 检查是否为检验模式
|
||||||
if config.IsType == 1 {
|
if config.IsType == 1 {
|
||||||
// 检验模式:直接获取分享信息
|
// 检验模式:直接获取分享信息
|
||||||
urls := map[string]interface{}{
|
urls := map[string]interface{}{
|
||||||
"title": "",
|
"title": shareDetail["title"],
|
||||||
"share_url": config.URL,
|
"share_url": config.URL,
|
||||||
"stoken": "",
|
"stoken": "",
|
||||||
}
|
}
|
||||||
return SuccessResult("检验成功", urls), nil
|
return SuccessResult("检验成功", urls), nil
|
||||||
}
|
}
|
||||||
files := shareDetail["files"].([]interface{})
|
|
||||||
|
|
||||||
// 转存到网盘
|
// files := shareDetail["files"].([]interface{})
|
||||||
parent_id := "0" // 默认存储路径
|
// fileIDs := make([]string, 0)
|
||||||
if config.ExpiredType == 2 {
|
// for _, file := range files {
|
||||||
parent_id = "指定路径" // 这里可能需要从配置获取
|
// fileMap := file.(map[string]interface{})
|
||||||
}
|
// if fid, ok := fileMap["id"].(string); ok {
|
||||||
|
// fileIDs = append(fileIDs, fid)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
fileIDs := make([]string, 0)
|
// 处理广告过滤(这里简化处理)
|
||||||
for _, file := range files {
|
// TODO: 添加广告文件过滤逻辑
|
||||||
fileMap := file.(map[string]interface{})
|
|
||||||
if fid, ok := fileMap["id"].(string); ok {
|
|
||||||
fileIDs = append(fileIDs, fid)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(fileIDs) == 0 {
|
|
||||||
return ErrorResult("分享中没有可转存的文件"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转存资源
|
// 转存资源
|
||||||
restoreResult, err := x.getRestore(shareID, shareDetail, accessToken, captchaToken, parent_id)
|
restoreResult, err := x.getRestore(shareID, shareDetail, accessToken, captchaToken, parent_id)
|
||||||
@@ -381,43 +382,27 @@ func (x *XunleiPanService) Transfer(shareID string) (*TransferResult, error) {
|
|||||||
return ErrorResult(fmt.Sprintf("转存失败: %v", err)), nil
|
return ErrorResult(fmt.Sprintf("转存失败: %v", err)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if restoreResult["code"].(int) != 200 {
|
|
||||||
return ErrorResult("转存失败"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取转存任务信息
|
// 获取转存任务信息
|
||||||
restoreData := restoreResult["data"].(map[string]interface{})
|
taskID := restoreResult["restore_task_id"].(string)
|
||||||
taskID := restoreData["restore_task_id"].(string)
|
|
||||||
|
|
||||||
// 等待转存完成
|
// 等待转存完成
|
||||||
_, err = x.waitForTask(taskID, accessToken, captchaToken)
|
taskResp, err := x.waitForTask(taskID, accessToken, captchaToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ErrorResult(fmt.Sprintf("等待转存完成失败: %v", err)), nil
|
return ErrorResult(fmt.Sprintf("等待转存完成失败: %v", err)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取任务结果并解析文件ID
|
|
||||||
// 获取任务结果以获取文件ID
|
// 获取任务结果以获取文件ID
|
||||||
existingFileIds := make([]string, 0)
|
existingFileIds := make([]string, 0)
|
||||||
taskResp, err := x.getTasks(taskID, accessToken, captchaToken)
|
if params, ok2 := taskResp["params"].(map[string]interface{}); ok2 {
|
||||||
if err != nil {
|
if traceIds, ok3 := params["trace_file_ids"].(string); ok3 {
|
||||||
return ErrorResult(fmt.Sprintf("获取任务结果失败: %v", err)), nil
|
traceData := make(map[string]interface{})
|
||||||
}
|
json.Unmarshal([]byte(traceIds), &traceData)
|
||||||
|
for _, fid := range traceData {
|
||||||
if taskData, ok := taskResp["data"].(map[string]interface{}); ok {
|
existingFileIds = append(existingFileIds, fid.(string))
|
||||||
if params, ok2 := taskData["params"].(map[string]interface{}); ok2 {
|
|
||||||
if traceIds, ok3 := params["trace_file_ids"].(string); ok3 {
|
|
||||||
traceData := make(map[string]interface{})
|
|
||||||
json.Unmarshal([]byte(traceIds), &traceData)
|
|
||||||
for _, fid := range traceData {
|
|
||||||
existingFileIds = append(existingFileIds, fid.(string))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理广告过滤(这里简化处理)
|
|
||||||
// TODO: 添加广告文件过滤逻辑
|
|
||||||
|
|
||||||
// 创建分享链接
|
// 创建分享链接
|
||||||
expirationDays := "-1"
|
expirationDays := "-1"
|
||||||
if config.ExpiredType == 2 {
|
if config.ExpiredType == 2 {
|
||||||
@@ -425,36 +410,30 @@ func (x *XunleiPanService) Transfer(shareID string) (*TransferResult, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 根据share_id获取到分享链接
|
// 根据share_id获取到分享链接
|
||||||
passwordResult, err := x.getSharePassword(existingFileIds, accessToken, captchaToken, expirationDays)
|
shareResult, err := x.getSharePassword(existingFileIds, accessToken, captchaToken, expirationDays)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ErrorResult(fmt.Sprintf("创建分享链接失败: %v", err)), nil
|
return ErrorResult(fmt.Sprintf("创建分享链接失败: %v", err)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if passwordResult["code"].(int) != 200 {
|
var fid string
|
||||||
return ErrorResult("创建分享链接失败"), nil
|
if len(existingFileIds) > 1 {
|
||||||
}
|
fid = strings.Join(existingFileIds, ",")
|
||||||
|
} else {
|
||||||
passwordData := passwordResult["data"].(map[string]interface{})
|
fid = existingFileIds[0]
|
||||||
shareTitle := ""
|
|
||||||
if len(files) > 0 {
|
|
||||||
file0 := files[0].(map[string]interface{})
|
|
||||||
if name, ok := file0["name"].(string); ok {
|
|
||||||
shareTitle = name
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result := map[string]interface{}{
|
result := map[string]interface{}{
|
||||||
"title": shareTitle,
|
"title": "",
|
||||||
"share_url": passwordData["share_url"].(string) + "?pwd=" + passwordData["pass_code"].(string),
|
"shareUrl": shareResult["share_url"].(string) + "?pwd=" + shareResult["pass_code"].(string),
|
||||||
"code": passwordData["pass_code"].(string),
|
"code": shareResult["pass_code"].(string),
|
||||||
"fid": existingFileIds,
|
"fid": fid,
|
||||||
}
|
}
|
||||||
|
|
||||||
return SuccessResult("转存成功", result), nil
|
return SuccessResult("转存成功", result), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// waitForTask 等待任务完成 - 使用 HTTPGet 方法
|
// waitForTask 等待任务完成 - 使用 HTTPGet 方法
|
||||||
func (x *XunleiPanService) waitForTask(taskID string, accessToken, captchaToken string) (*XLTaskResult, error) {
|
func (x *XunleiPanService) waitForTask(taskID string, accessToken, captchaToken string) (map[string]interface{}, error) {
|
||||||
maxRetries := 50
|
maxRetries := 50
|
||||||
retryDelay := 2 * time.Second
|
retryDelay := 2 * time.Second
|
||||||
|
|
||||||
@@ -464,7 +443,7 @@ func (x *XunleiPanService) waitForTask(taskID string, accessToken, captchaToken
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if result.Status == 2 { // 任务完成
|
if int64(result["progress"].(float64)) == 100 { // 任务完成
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -475,12 +454,9 @@ func (x *XunleiPanService) waitForTask(taskID string, accessToken, captchaToken
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getTaskStatus 获取任务状态 - 使用 HTTPGet 方法
|
// getTaskStatus 获取任务状态 - 使用 HTTPGet 方法
|
||||||
func (x *XunleiPanService) getTaskStatus(taskID string, retryIndex int, accessToken, captchaToken string) (*XLTaskResult, error) {
|
func (x *XunleiPanService) getTaskStatus(taskID string, retryIndex int, accessToken, captchaToken string) (map[string]interface{}, error) {
|
||||||
apiURL := x.apiHost("") + "/drive/v1/task"
|
apiURL := x.apiHost("") + "/drive/v1/tasks/" + taskID
|
||||||
queryParams := map[string]string{
|
queryParams := map[string]string{}
|
||||||
"task_id": taskID,
|
|
||||||
"retry_index": fmt.Sprintf("%d", retryIndex),
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置 request 所需的 headers
|
// 设置 request 所需的 headers
|
||||||
headers := map[string]string{
|
headers := map[string]string{
|
||||||
@@ -492,17 +468,7 @@ func (x *XunleiPanService) getTaskStatus(taskID string, retryIndex int, accessTo
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return resp, nil
|
||||||
if code, ok := resp["code"].(float64); ok && code != 200 {
|
|
||||||
return nil, fmt.Errorf("获取任务状态失败")
|
|
||||||
}
|
|
||||||
|
|
||||||
var data XLTaskResult
|
|
||||||
resultBytes, _ := json.Marshal(resp)
|
|
||||||
if err := json.Unmarshal(resultBytes, &data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &data, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserInfoByEntity 根据 entity.Cks 获取用户信息(待实现)
|
// GetUserInfoByEntity 根据 entity.Cks 获取用户信息(待实现)
|
||||||
|
|||||||
@@ -1,449 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace netdisk\pan;
|
|
||||||
|
|
||||||
class QuarkPan extends BasePan
|
|
||||||
{
|
|
||||||
public function __construct($config = [])
|
|
||||||
{
|
|
||||||
parent::__construct($config);
|
|
||||||
$this->urlHeader = [
|
|
||||||
'Accept: application/json, text/plain, */*',
|
|
||||||
'Accept-Language: zh-CN,zh;q=0.9',
|
|
||||||
'content-type: application/json;charset=UTF-8',
|
|
||||||
'sec-ch-ua: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',
|
|
||||||
'sec-ch-ua-mobile: ?0',
|
|
||||||
'sec-ch-ua-platform: "Windows"',
|
|
||||||
'sec-fetch-dest: empty',
|
|
||||||
'sec-fetch-mode: cors',
|
|
||||||
'sec-fetch-site: same-site',
|
|
||||||
'Referer: https://pan.quark.cn/',
|
|
||||||
'Referrer-Policy: strict-origin-when-cross-origin',
|
|
||||||
'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
|
||||||
'cookie: ' . Config('qfshop.quark_cookie')
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFiles($pdir_fid=0)
|
|
||||||
{
|
|
||||||
// 原 getFiles 方法内容
|
|
||||||
$urlData = [];
|
|
||||||
$queryParams = [
|
|
||||||
'pr' => 'ucpro',
|
|
||||||
'fr' => 'pc',
|
|
||||||
'uc_param_str' => '',
|
|
||||||
'pdir_fid' => $pdir_fid,
|
|
||||||
'_page' => 1,
|
|
||||||
'_size' => 50,
|
|
||||||
'_fetch_total' => 1,
|
|
||||||
'_fetch_sub_dirs' => 0,
|
|
||||||
'_sort' => 'file_type:asc,updated_at:desc',
|
|
||||||
];
|
|
||||||
|
|
||||||
$res = curlHelper("https://drive-pc.quark.cn/1/clouddrive/file/sort", "GET", json_encode($urlData), $this->urlHeader,$queryParams)['body'];
|
|
||||||
$res = json_decode($res, true);
|
|
||||||
if($res['status'] !== 200){
|
|
||||||
return jerr2($res['message']=='require login [guest]'?'夸克未登录,请检查cookie':$res['message']);
|
|
||||||
}
|
|
||||||
|
|
||||||
return jok2('获取成功',$res['data']['list']);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function transfer($pwd_id)
|
|
||||||
{
|
|
||||||
if(empty($this->stoken)){
|
|
||||||
//获取要转存夸克资源的stoken
|
|
||||||
$res = $this->getStoken($pwd_id);
|
|
||||||
if($res['status'] !== 200) return jerr2($res['message']);
|
|
||||||
$infoData = $res['data'];
|
|
||||||
|
|
||||||
if($this->isType == 1){
|
|
||||||
$urls['title'] = $infoData['title'];
|
|
||||||
$urls['share_url'] = $this->url;
|
|
||||||
$urls['stoken'] = $infoData['stoken'];
|
|
||||||
return jok2('检验成功', $urls);
|
|
||||||
}
|
|
||||||
$stoken = $infoData['stoken'];
|
|
||||||
$stoken = str_replace(' ', '+', $stoken);
|
|
||||||
}else{
|
|
||||||
$stoken = str_replace(' ', '+', $this->stoken);
|
|
||||||
}
|
|
||||||
|
|
||||||
//获取要转存夸克资源的详细内容
|
|
||||||
$res = $this->getShare($pwd_id,$stoken);
|
|
||||||
if($res['status']!== 200) return jerr2($res['message']);
|
|
||||||
$detail = $res['data'];
|
|
||||||
|
|
||||||
$fid_list = [];
|
|
||||||
$fid_token_list = [];
|
|
||||||
$title = $detail['share']['title']; //资源名称
|
|
||||||
foreach ($detail['list'] as $key => $value) {
|
|
||||||
$fid_list[] = $value['fid'];
|
|
||||||
$fid_token_list[] = $value['share_fid_token'];
|
|
||||||
}
|
|
||||||
|
|
||||||
//转存资源到指定文件夹
|
|
||||||
$res = $this->getShareSave($pwd_id,$stoken,$fid_list,$fid_token_list);
|
|
||||||
if($res['status']!== 200) return jerr2($res['message']);
|
|
||||||
$task_id = $res['data']['task_id'];
|
|
||||||
|
|
||||||
//转存后根据task_id获取转存到自己网盘后的信息
|
|
||||||
$retry_index = 0;
|
|
||||||
$myData = '';
|
|
||||||
while ($myData=='' || $myData['status'] != 2) {
|
|
||||||
$res = $this->getShareTask($task_id, $retry_index);
|
|
||||||
if($res['message']== 'capacity limit[{0}]'){
|
|
||||||
return jerr2('容量不足');
|
|
||||||
}
|
|
||||||
if($res['status']!== 200) {
|
|
||||||
return jerr2($res['message']);
|
|
||||||
}
|
|
||||||
$myData = $res['data'];
|
|
||||||
$retry_index++;
|
|
||||||
// 可以添加一个最大重试次数的限制,防止无限循环
|
|
||||||
if ($retry_index > 50) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
//删除转存后可能有的广告
|
|
||||||
$banned = Config('qfshop.quark_banned')??''; //如果出现这些字样就删除
|
|
||||||
if(!empty($banned)){
|
|
||||||
$bannedList = explode(',', $banned);
|
|
||||||
$pdir_fid = $myData['save_as']['save_as_top_fids'][0];
|
|
||||||
$dellist = [];
|
|
||||||
$plist = $this->getPdirFid($pdir_fid);
|
|
||||||
if(!empty($plist)){
|
|
||||||
foreach ($plist as $key => $value) {
|
|
||||||
// 检查$value['file_name']是否包含$bannedList中的任何一项
|
|
||||||
$contains = false;
|
|
||||||
foreach ($bannedList as $item) {
|
|
||||||
if (strpos($value['file_name'], $item) !== false) {
|
|
||||||
$contains = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($contains) {
|
|
||||||
$dellist[] = $value['fid'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(count($plist) === count($dellist)){
|
|
||||||
//要删除的资源数如果和原数据资源数一样 就全部删除并终止下面的分享
|
|
||||||
$this->deletepdirFid([$pdir_fid]);
|
|
||||||
return jerr2("资源内容为空");
|
|
||||||
}else{
|
|
||||||
if (!empty($dellist)) {
|
|
||||||
$this->deletepdirFid($dellist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$shareFid = $myData['save_as']['save_as_top_fids'];
|
|
||||||
//分享资源并拿到更新后的task_id
|
|
||||||
$res = $this->getShareBtn($myData['save_as']['save_as_top_fids'],$title);
|
|
||||||
if($res['status']!== 200) return jerr2($res['message']);
|
|
||||||
$task_id = $res['data']['task_id'];
|
|
||||||
|
|
||||||
//根据task_id拿到share_id
|
|
||||||
$retry_index = 0;
|
|
||||||
$myData = '';
|
|
||||||
while ($myData=='' || $myData['status'] != 2) {
|
|
||||||
$res = $this->getShareTask($task_id, $retry_index);
|
|
||||||
if($res['status']!== 200) continue;
|
|
||||||
$myData = $res['data'];
|
|
||||||
$retry_index++;
|
|
||||||
// 可以添加一个最大重试次数的限制,防止无限循环
|
|
||||||
if ($retry_index > 50) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//根据share_id 获取到分享链接
|
|
||||||
$res = $this->getSharePassword($myData['share_id']);
|
|
||||||
if($res['status']!== 200) return jerr2($res['message']);
|
|
||||||
$share = $res['data'];
|
|
||||||
// $share['fid'] = $share['first_file']['fid'];
|
|
||||||
$share['fid'] = (is_array($shareFid) && count($shareFid) > 1) ? $shareFid : $share['first_file']['fid'];
|
|
||||||
|
|
||||||
return jok2('转存成功', $share);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取要转存资源的stoken
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function getStoken($pwd_id)
|
|
||||||
{
|
|
||||||
$urlData = array(
|
|
||||||
'passcode' => '',
|
|
||||||
'pwd_id' => $pwd_id,
|
|
||||||
);
|
|
||||||
$queryParams = [
|
|
||||||
'pr' => 'ucpro',
|
|
||||||
'fr' => 'pc',
|
|
||||||
'uc_param_str' => '',
|
|
||||||
];
|
|
||||||
return $this->executeApiRequest(
|
|
||||||
"https://drive-pc.quark.cn/1/clouddrive/share/sharepage/token",
|
|
||||||
"POST",
|
|
||||||
$urlData,
|
|
||||||
$queryParams
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取要转存资源的详细内容
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function getShare($pwd_id,$stoken)
|
|
||||||
{
|
|
||||||
$urlData = array();
|
|
||||||
$queryParams = [
|
|
||||||
"pr" => "ucpro",
|
|
||||||
"fr" => "pc",
|
|
||||||
"uc_param_str" => "",
|
|
||||||
"pwd_id" => $pwd_id,
|
|
||||||
"stoken" => $stoken,
|
|
||||||
"pdir_fid" => "0",
|
|
||||||
"force" => "0",
|
|
||||||
"_page" => "1",
|
|
||||||
"_size" => "100",
|
|
||||||
"_fetch_banner" => "1",
|
|
||||||
"_fetch_share" => "1",
|
|
||||||
"_fetch_total" => "1",
|
|
||||||
"_sort" => "file_type:asc,updated_at:desc"
|
|
||||||
];
|
|
||||||
return $this->executeApiRequest(
|
|
||||||
"https://drive-pc.quark.cn/1/clouddrive/share/sharepage/detail",
|
|
||||||
"GET",
|
|
||||||
$urlData,
|
|
||||||
$queryParams
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 转存资源到指定文件夹
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function getShareSave($pwd_id,$stoken,$fid_list,$fid_token_list)
|
|
||||||
{
|
|
||||||
if(!empty($this->to_pdir_fid)){
|
|
||||||
$to_pdir_fid = $this->to_pdir_fid;
|
|
||||||
}else{
|
|
||||||
$to_pdir_fid = Config('qfshop.quark_file'); //默认存储路径
|
|
||||||
if($this->expired_type == 2){
|
|
||||||
$to_pdir_fid = Config('qfshop.quark_file_time'); //临时资源路径
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$urlData = array(
|
|
||||||
'fid_list' => $fid_list,
|
|
||||||
'fid_token_list' => $fid_token_list,
|
|
||||||
'to_pdir_fid' => $to_pdir_fid,
|
|
||||||
'pwd_id' => $pwd_id,
|
|
||||||
'stoken' => $stoken,
|
|
||||||
'pdir_fid' => "0",
|
|
||||||
'scene' => "link",
|
|
||||||
);
|
|
||||||
$queryParams = [
|
|
||||||
"entry" => "update_share",
|
|
||||||
"pr" => "ucpro",
|
|
||||||
"fr" => "pc",
|
|
||||||
"uc_param_str" => ""
|
|
||||||
];
|
|
||||||
|
|
||||||
return $this->executeApiRequest(
|
|
||||||
"https://drive-pc.quark.cn/1/clouddrive/share/sharepage/save",
|
|
||||||
"POST",
|
|
||||||
$urlData,
|
|
||||||
$queryParams
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分享资源拿到task_id
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function getShareBtn($fid_list,$title)
|
|
||||||
{
|
|
||||||
if(!empty($this->ad_fid)){
|
|
||||||
$fid_list[] = $this->ad_fid;
|
|
||||||
}
|
|
||||||
$urlData = array(
|
|
||||||
'fid_list' => $fid_list,
|
|
||||||
'expired_type' => $this->expired_type,
|
|
||||||
'title' => $title,
|
|
||||||
'url_type' => 1,
|
|
||||||
);
|
|
||||||
$queryParams = [
|
|
||||||
"pr" => "ucpro",
|
|
||||||
"fr" => "pc",
|
|
||||||
"uc_param_str" => ""
|
|
||||||
];
|
|
||||||
|
|
||||||
return $this->executeApiRequest(
|
|
||||||
"https://drive-pc.quark.cn/1/clouddrive/share",
|
|
||||||
"POST",
|
|
||||||
$urlData,
|
|
||||||
$queryParams
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据task_id拿到自己的资源信息
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function getShareTask($task_id,$retry_index)
|
|
||||||
{
|
|
||||||
$urlData = array();
|
|
||||||
$queryParams = [
|
|
||||||
"pr" => "ucpro",
|
|
||||||
"fr" => "pc",
|
|
||||||
"uc_param_str" => "",
|
|
||||||
"task_id" => $task_id,
|
|
||||||
"retry_index" => $retry_index
|
|
||||||
];
|
|
||||||
return $this->executeApiRequest(
|
|
||||||
"https://drive-pc.quark.cn/1/clouddrive/task",
|
|
||||||
"GET",
|
|
||||||
$urlData,
|
|
||||||
$queryParams
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据share_id 获取到分享链接
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function getSharePassword($share_id)
|
|
||||||
{
|
|
||||||
$urlData = array(
|
|
||||||
'share_id' => $share_id,
|
|
||||||
);
|
|
||||||
$queryParams = [
|
|
||||||
"pr" => "ucpro",
|
|
||||||
"fr" => "pc",
|
|
||||||
"uc_param_str" => ""
|
|
||||||
];
|
|
||||||
return $this->executeApiRequest(
|
|
||||||
"https://drive-pc.quark.cn/1/clouddrive/share/password",
|
|
||||||
"POST",
|
|
||||||
$urlData,
|
|
||||||
$queryParams
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除指定资源
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function deletepdirFid($filelist)
|
|
||||||
{
|
|
||||||
$urlData = array(
|
|
||||||
'action_type' => 2,
|
|
||||||
'exclude_fids' => [],
|
|
||||||
'filelist' => $filelist,
|
|
||||||
);
|
|
||||||
$queryParams = [
|
|
||||||
"pr" => "ucpro",
|
|
||||||
"fr" => "pc",
|
|
||||||
"uc_param_str" => ""
|
|
||||||
];
|
|
||||||
return $this->executeApiRequest(
|
|
||||||
"https://drive-pc.quark.cn/1/clouddrive/file/delete",
|
|
||||||
"POST",
|
|
||||||
$urlData,
|
|
||||||
$queryParams
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取夸克网盘指定文件夹内容
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function getPdirFid($pdir_fid)
|
|
||||||
{
|
|
||||||
$urlData = [];
|
|
||||||
$queryParams = [
|
|
||||||
'pr' => 'ucpro',
|
|
||||||
'fr' => 'pc',
|
|
||||||
'uc_param_str' => '',
|
|
||||||
'pdir_fid' => $pdir_fid,
|
|
||||||
'_page' => 1,
|
|
||||||
'_size' => 200,
|
|
||||||
'_fetch_total' => 1,
|
|
||||||
'_fetch_sub_dirs' => 0,
|
|
||||||
'_sort' => 'file_type:asc,updated_at:desc',
|
|
||||||
];
|
|
||||||
try {
|
|
||||||
$res = curlHelper("https://drive-pc.quark.cn/1/clouddrive/file/sort", "GET", json_encode($urlData), $this->urlHeader,$queryParams)['body'];
|
|
||||||
$res = json_decode($res, true);
|
|
||||||
if($res['status'] !== 200){
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return $res['data']['list'];
|
|
||||||
} catch (\Throwable $e) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行API请求并处理重试逻辑
|
|
||||||
*
|
|
||||||
* @param string $url 请求URL
|
|
||||||
* @param string $method 请求方法(GET/POST)
|
|
||||||
* @param array $data 请求数据
|
|
||||||
* @param array $queryParams 查询参数
|
|
||||||
* @param int $maxRetries 最大重试次数
|
|
||||||
* @param int $retryDelay 重试延迟(秒)
|
|
||||||
* @return array 响应结果
|
|
||||||
*/
|
|
||||||
protected function executeApiRequest($url, $method, $data = [], $queryParams = [], $maxRetries = 3, $retryDelay = 2)
|
|
||||||
{
|
|
||||||
$attempt = 0;
|
|
||||||
while ($attempt < $maxRetries) {
|
|
||||||
$attempt++;
|
|
||||||
try {
|
|
||||||
$res = curlHelper($url, $method, json_encode($data), $this->urlHeader, $queryParams)['body'];
|
|
||||||
return json_decode($res, true);
|
|
||||||
} catch (\Throwable $e) {
|
|
||||||
$this->logApiError($url, $attempt, $e->getMessage());
|
|
||||||
if ($attempt < $maxRetries) {
|
|
||||||
sleep($retryDelay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ['status' => 500, 'message' => '接口请求异常'];
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 记录API错误日志
|
|
||||||
*
|
|
||||||
* @param string $prefix 日志前缀
|
|
||||||
* @param int $attempt 尝试次数
|
|
||||||
* @param mixed $error 错误信息
|
|
||||||
*/
|
|
||||||
protected function logApiError($prefix, $attempt, $error)
|
|
||||||
{
|
|
||||||
$errorMsg = is_scalar($error) ? $error : json_encode($error);
|
|
||||||
$logMessage = date('Y-m-d H:i:s') . ' ' . $prefix . '请求失败(尝试次数: ' . $attempt . ') 错误: ' . $errorMsg . "\n";
|
|
||||||
file_put_contents('error.log', $logMessage, FILE_APPEND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -464,6 +464,7 @@ func GetResourceLink(c *gin.Context) {
|
|||||||
// TransferResult 转存结果
|
// TransferResult 转存结果
|
||||||
type TransferResult struct {
|
type TransferResult struct {
|
||||||
Success bool `json:"success"`
|
Success bool `json:"success"`
|
||||||
|
Fid string `json:"fid"`
|
||||||
SaveURL string `json:"save_url"`
|
SaveURL string `json:"save_url"`
|
||||||
ErrorMsg string `json:"error_msg"`
|
ErrorMsg string `json:"error_msg"`
|
||||||
}
|
}
|
||||||
@@ -525,6 +526,8 @@ func performAutoTransfer(resource *entity.Resource) TransferResult {
|
|||||||
if result.Success {
|
if result.Success {
|
||||||
// 更新资源的转存信息
|
// 更新资源的转存信息
|
||||||
resource.SaveURL = result.SaveURL
|
resource.SaveURL = result.SaveURL
|
||||||
|
resource.Fid = result.Fid
|
||||||
|
resource.CkID = &account.ID
|
||||||
resource.ErrorMsg = ""
|
resource.ErrorMsg = ""
|
||||||
if err := repoManager.ResourceRepository.Update(resource); err != nil {
|
if err := repoManager.ResourceRepository.Update(resource); err != nil {
|
||||||
utils.Error("更新资源转存信息失败: %v", err)
|
utils.Error("更新资源转存信息失败: %v", err)
|
||||||
@@ -594,10 +597,15 @@ func transferSingleResource(resource *entity.Resource, account entity.Cks, facto
|
|||||||
|
|
||||||
// 提取转存链接
|
// 提取转存链接
|
||||||
var saveURL string
|
var saveURL string
|
||||||
|
var fid string
|
||||||
|
|
||||||
if data, ok := transferResult.Data.(map[string]interface{}); ok {
|
if data, ok := transferResult.Data.(map[string]interface{}); ok {
|
||||||
if v, ok := data["shareUrl"]; ok {
|
if v, ok := data["shareUrl"]; ok {
|
||||||
saveURL, _ = v.(string)
|
saveURL, _ = v.(string)
|
||||||
}
|
}
|
||||||
|
if v, ok := data["fid"]; ok {
|
||||||
|
fid, _ = v.(string)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if saveURL == "" {
|
if saveURL == "" {
|
||||||
saveURL = transferResult.ShareURL
|
saveURL = transferResult.ShareURL
|
||||||
@@ -615,6 +623,7 @@ func transferSingleResource(resource *entity.Resource, account entity.Cks, facto
|
|||||||
return TransferResult{
|
return TransferResult{
|
||||||
Success: true,
|
Success: true,
|
||||||
SaveURL: saveURL,
|
SaveURL: saveURL,
|
||||||
|
Fid: fid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user