import { DOMUtils, httpx, log, utils } from "@/env";
import { ParseFileCore } from "@/main/handler/parse/NetDiskParseAbstract";
import { NetDiskLinkClickMode, NetDiskLinkClickModeUtils } from "@/main/link-click-mode/NetDiskLinkClickMode";
import { NetDiskFilterScheme } from "@/main/scheme/NetDiskFilterScheme";
import { NetDiskView } from "@/main/view/NetDiskView";
import type { PopsFolderDataConfig } from "@whitesev/pops/dist/types/src/components/folder/types/index.js";
import type { HttpxResponse } from "@whitesev/utils/dist/types/src/types/Httpx.js";
import Qmsg from "qmsg";
import { unsafeWindow } from "ViteGM";
/**
* 阿里云解析下载已失效
*/
export class NetDiskParse_Aliyun extends ParseFileCore {
X_Share_Token_Data = {
expire_time: "2000-01-01T00:00:00.000Z",
expires_in: 7200,
share_token: "",
};
/**
* header请求头 X-Device-Id
*/
X_Device_Id = null;
/**
* header请求头 X-Canary
*/
X_Canary = "client=web,app=share,version=v2.3.1";
async init(netDiskInfo: ParseFileInitConfig) {
super.init(netDiskInfo);
const that = this;
let { ruleIndex, shareCode, accessCode } = netDiskInfo;
that.X_Device_Id = that.get_X_Device_Id();
log.info("生成X_Device_Id:" + that.X_Device_Id);
if (globalThis.location.hostname !== "www.aliyundrive.com" && globalThis.location.hostname !== "www.alipan.com") {
let url = NetDiskLinkClickModeUtils.getBlankUrl({
ruleKeyName: "aliyun",
ruleIndex,
shareCode,
accessCode,
});
let $QmsgErrorTip = Qmsg.error(`请在阿里云盘页面解析,点我前往`, {
timeout: 10000,
isHTML: true,
});
DOMUtils.on($QmsgErrorTip.$el.$item.querySelector("a[href]"), "click", (event) => {
DOMUtils.preventEvent(event);
NetDiskLinkClickMode.openBlankUrl(url, "aliyun", that.ruleIndex, that.shareCode, that.accessCode);
});
return;
}
const $loading = Qmsg.loading("正在解析,请稍后...");
const detail = await this.list_by_share(shareCode, "root");
if (!detail) {
$loading.close();
return;
}
$loading.setText("正在解析多文件...");
const folderInfoList = that.getFolderInfo(detail, 0);
log.info("解析完毕");
$loading.close();
NetDiskView.$inst.linearChainDialogView.moreFile("阿里云盘文件解析", folderInfoList);
}
/**
* 弹窗使用-获取文件夹信息
* @param infoList
*/
getFolderInfo(
infoList: {
category?: string;
domain_id?: string;
file_extension?: string;
mime_extension?: string;
mime_type?: string;
punish_flag: number;
created_at: string;
drive_id: string;
file_id: string;
name: string;
parent_file_id: string;
share_id: string;
type: string;
updated_at: string;
}[],
index = 0
) {
const folderInfoList: PopsFolderDataConfig[] = [];
infoList.forEach((item: any) => {
if (item.type !== "folder") {
// 文件
folderInfoList.push({
fileName: item.name,
fileSize: item.size,
fileType: item.file_extension,
createTime: new Date(item.created_at).getTime(),
latestTime: new Date(item.updated_at).getTime(),
isFolder: false,
index: index,
clickEvent: async () => {
const $loading = Qmsg.loading("正在获取下载链接...");
const fileDownloadUrl = await this.get_share_link_download_url(item.share_id, item.file_id);
$loading.close();
if (!fileDownloadUrl) {
return;
}
let schemeDownloadUrl = fileDownloadUrl;
if (NetDiskFilterScheme.isForwardDownloadLink("aliyun")) {
schemeDownloadUrl = NetDiskFilterScheme.parseDataToSchemeUri("aliyun", schemeDownloadUrl);
}
return {
mode: "aBlank",
url: schemeDownloadUrl,
};
},
});
} else {
// 文件夹
folderInfoList.push({
fileName: item.name,
fileSize: 0,
fileType: "",
createTime: item.created_at,
latestTime: item.updated_at,
isFolder: true,
index: index,
clickEvent: async () => {
const __infoList = await this.list_by_share(item.share_id, item.file_id);
if (__infoList) {
return this.getFolderInfo(__infoList, index + 1);
} else {
return [];
}
},
});
}
});
return folderInfoList;
}
/**
* 列出文件列表
* @param share_id
* @param parent_file_id 父项,根是root
* @param order_by 根据xxx排序
* @param order_direction 排序规则(升序/降序)
*/
async list_by_share(
share_id: string,
parent_file_id: string,
order_by: string = "name",
order_direction: "ASC" | "DESC" = "DESC"
) {
const that = this;
let postResp = await httpx.post("https://api.aliyundrive.com/adrive/v2/file/list_by_share", {
data: JSON.stringify({
share_id: share_id,
parent_file_id: parent_file_id,
limit: 20,
image_thumbnail_process: "image/resize,w_256/format,jpeg",
image_url_process: "image/resize,w_1920/format,jpeg/interlace,1",
video_thumbnail_process: "video/snapshot,t_1000,f_jpg,ar_auto,w_256",
order_by: order_by,
order_direction: order_direction,
}),
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/json",
Origin: "https://www.aliyundrive.com",
Referer: "https://www.aliyundrive.com/",
"X-Canary": that.X_Canary,
"X-Device-Id": that.X_Device_Id,
"X-Share-Token": await that.get_X_Share_Token(that.shareCode, that.accessCode),
"User-Agent": utils.getRandomPCUA(),
},
allowInterceptConfig: false,
});
if (!postResp.status) {
that.handle_request_error(postResp);
return;
}
let data = utils.toJSON(postResp.data.responseText);
log.info("列出文件列表:", data);
return data["items"] as {
category?: string;
domain_id?: string;
file_extension?: string;
mime_extension?: string;
mime_type?: string;
punish_flag: number;
created_at: string;
drive_id: string;
file_id: string;
name: string;
parent_file_id: string;
share_id: string;
type: string;
updated_at: string;
}[];
}
/**
* 获取文件的下载链接
* @param share_id
* @param file_id
*/
async get_share_link_download_url(share_id: string, file_id: string) {
const that = this;
let postResp = await httpx.post("https://api.aliyundrive.com/v2/file/get_share_link_download_url", {
data: JSON.stringify({
expire_sec: 600,
file_id: file_id,
share_id: share_id,
}),
headers: {
Accept: "application/json, text/plain, */*",
Origin: "https://www.aliyundrive.com",
Referer: "https://www.aliyundrive.com/",
"Content-Type": "application/json;charset=UTF-8",
Authorization: "Bearer " + that.getAuthorization(),
"X-Share-Token": await that.get_X_Share_Token(that.shareCode, that.accessCode),
"User-Agent": utils.getRandomPCUA(),
},
responseType: "arraybuffer",
allowInterceptConfig: false,
});
if (!postResp.status) {
that.handle_request_error(postResp);
return;
}
let data = utils.toJSON(postResp.data.responseText);
log.info("获取文件的下载链接:", data);
return data["download_url"] as string;
}
/**
* 处理请求的错误
* @param response
*/
handle_request_error(response: HttpxResponse) {
log.error(response);
const data = utils.toJSON(response.data.responseText);
const message = data["message"];
if (typeof message === "string" && message.trim() !== "") {
Qmsg.error(message);
return true;
} else if (typeof data.code === "string" && data.code.trim() !== "") {
Qmsg.error(data.code);
} else if (typeof response.msg === "string" && response.msg.trim() !== "") {
Qmsg.error(response.msg);
return true;
} else {
return false;
}
}
/**
* 获取用户鉴权值
* 来源:localStorage => token.access_token
*/
getAuthorization() {
let token = unsafeWindow.localStorage.getItem("token");
if (utils.isNotNull(token) && token != null) {
let tokenJSON = utils.toJSON(token);
let access_token = tokenJSON["access_token"];
log.success("获取阿里云盘的access_token:", access_token);
return access_token as string;
} else {
Qmsg.error("获取access_token失败,请先登录账号!");
}
}
/**
* 获取header请求头 X-Share-Token
* 来源:localStorage => shareToken.share_token
* @param share_id
* @param share_pwd
*/
async get_X_Share_Token(share_id: string, share_pwd: AccessCodeNonNullType) {
const that = this;
if (new Date() < new Date(that.X_Share_Token_Data.expire_time)) {
return that.X_Share_Token_Data.share_token;
}
let postResp = await httpx.post("https://api.aliyundrive.com/v2/share_link/get_share_token", {
data: JSON.stringify({
share_id: share_id,
share_pwd: share_pwd,
}),
headers: {
Accept: "application/json, text/plain, */*",
"Content-Type": "application/json",
Origin: "https://www.aliyundrive.com",
Referer: "https://www.aliyundrive.com/",
"X-Canary": that.X_Canary,
"X-Device-Id": that.X_Device_Id,
"User-Agent": utils.getRandomPCUA(),
},
allowInterceptConfig: false,
});
if (!postResp.status) {
that.handle_request_error(postResp);
return;
}
let data = utils.toJSON(postResp.data.responseText);
that.X_Share_Token_Data = data;
log.info("获取share_token:", that.X_Share_Token_Data);
return that.X_Share_Token_Data["share_token"];
}
/**
* 获取header请求头 X-Device-Id
*/
get_X_Device_Id() {
const that = this;
for (
var alipan_device_id_pattern =
/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i,
alipan_s: any[] = [],
alipan_l = 0;
alipan_l < 256;
++alipan_l
)
alipan_s.push((alipan_l + 256).toString(16).substr(1));
function alipan_o() {
return crypto.getRandomValues(new Uint8Array(16));
}
var alipan_c = function (args_e: any) {
var second_arg = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : 0,
devices_id_string = (
alipan_s[args_e[second_arg + 0]] +
alipan_s[args_e[second_arg + 1]] +
alipan_s[args_e[second_arg + 2]] +
alipan_s[args_e[second_arg + 3]] +
"-" +
alipan_s[args_e[second_arg + 4]] +
alipan_s[args_e[second_arg + 5]] +
"-" +
alipan_s[args_e[second_arg + 6]] +
alipan_s[args_e[second_arg + 7]] +
"-" +
alipan_s[args_e[second_arg + 8]] +
alipan_s[args_e[second_arg + 9]] +
"-" +
alipan_s[args_e[second_arg + 10]] +
alipan_s[args_e[second_arg + 11]] +
alipan_s[args_e[second_arg + 12]] +
alipan_s[args_e[second_arg + 13]] +
alipan_s[args_e[second_arg + 14]] +
alipan_s[args_e[second_arg + 15]]
).toLowerCase();
if (
!(function (e) {
return "string" == typeof e && alipan_device_id_pattern.test(e);
})(devices_id_string)
)
throw TypeError("Stringified UUID is invalid");
return devices_id_string;
},
alipan_u = function (args_e?: any, args_t?: any, args_n?: any) {
var randomValue = (args_e = args_e || {}).random || (args_e.rng || alipan_o)();
if (((randomValue[6] = (15 & randomValue[6]) | 64), (randomValue[8] = (63 & randomValue[8]) | 128), args_t)) {
args_n = args_n || 0;
for (var i = 0; i < 16; ++i) args_t[args_n + i] = randomValue[i];
return args_t;
}
return alipan_c(randomValue);
};
return alipan_u();
}
}