// ==UserScript==
// @name 阿里云原画播放
// @version 1.1.3
// @author Author Moe
// @date 2023-03-04
// @description 在画质选项中加入原画播放选项,使用potplayer播放阿里云盘原画视频(需要安装potplayer插件)https://github.com/gene9831/AliyunDrivePotPlayer。【提示】抓的接口限制增加,账号可能被风控限速,请酌情使用
// @license AGPL-3.0-or-later
// @match *://www.aliyundrive.com/s/*
// @match *://www.aliyundrive.com/drive*
// @require https://unpkg.com/jquery@3.6.0/dist/jquery.min.js
// @require https://unpkg.com/bn.js@4.11.8/lib/bn.js
// @require https://unpkg.com/@lionello/secp256k1-js@1.1.0/src/secp256k1.js
// @connect aliyundrive.com
// @connect localhost
// @connect *
// @run-at document-idle
// @grant unsafeWindow
// @grant GM_xmlhttpRequest
// @grant GM_setClipboard
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_openInTab
// @grant GM_info
// @grant GM_registerMenuCommand
// @grant GM_cookie
// @icon https://gw.alicdn.com/imgextra/i3/O1CN01aj9rdD1GS0E8io11t_!!6000000000620-73-tps-16-16.ico
// @namespace https://greasyfork.org/users/1026976
// ==/UserScript==
(function () {
'use strict';
let g_drive_id = "", g_file_id = "", g_file_name = "", g_share_id = "";
let privateKey = "", publicKey = "";
let app_id = "", device_id = "",user_id = "";
let signature = "";
let headers={};
let api_url = {
"0": "https://api.aliyundrive.com/v2/file/get_share_link_download_url",
"1": "https://api.aliyundrive.com/v2/file/get_download_url"
};
let main = {
isType(obj) {
return Object.prototype.toString.call(obj).replace(/^\[object (.+)\]$/, '$1').toLowerCase();
},
post(url, data, headers, type) {
if (this.isType(data) === 'object') {
data = JSON.stringify(data);
}
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "POST", url, headers, data,
responseType: type || 'json',
onload: (res) => {
type === 'blob' ? resolve(res) : resolve(res.response || res.responseText);
},
onerror: (err) => {
reject(err);
},
});
});
},
getStorage(key) {
try {
return JSON.parse(localStorage.getItem(key));
} catch (e) {
return localStorage.getItem(key);
}
},
async getRealLink(d, f) {
let res = await this.post(api_url[1], {
drive_id: d,
file_id: f
}, headers);
//console.log("getRealLink", d,f,res);
if (res.url) {
return res.url;
}
return '';
},
async getPCSLink(f, s){
try {
let authorization = `${this.getStorage('token').token_type} ${this.getStorage('token').access_token}`;
let xShareToken = this.getStorage('shareToken').share_token;
let res = await this.post(api_url[0], {
expire_sec: 600,
file_id: g_file_id,
share_id: g_share_id
}, {
authorization,
"content-type": "application/json;charset=utf-8",
"x-share-token": xShareToken
});
if (res.download_url) {
return res.download_url;
}
} catch (e) {
//console.log('提示:请先登录网盘!');
}
},
initDefaultConfig() {
let value = [{
name: 'url-scheme',
value: 'potplayer://'
},];
value.forEach((v) => {
GM_getValue(v.name) === undefined && GM_setValue(v.name, v.value);
});
},
async initECDSAKey() {
let privateKeyBuf = window.crypto.getRandomValues(new Uint8Array(32));
privateKey = Secp256k1.uint256(privateKeyBuf, 16);
publicKey = Secp256k1.generatePublicKeyFromPrivateKeyData(privateKey);
publicKey = "04" + publicKey.x + publicKey.y;
app_id = "5dde4e1bdf9e4966b387ba58f4b3fdc3";
device_id = this.getStorage('token').device_id;
user_id = this.getStorage('token').user_id;
console.log("initECDSAKey",privateKeyBuf);
let nonce = 0;
//sign
let text = `${app_id}:${device_id}:${user_id}:${nonce}`;
let encoder = new TextEncoder();
let data = encoder.encode(text);
let hashBuffer = await crypto.subtle.digest('SHA-256', data);
//hashBuffer to uint8 array
hashBuffer = new Uint8Array(hashBuffer);
console.log("hashBuffer",hashBuffer);
let sig = Secp256k1.ecsign(privateKey, Secp256k1.uint256(hashBuffer, 16));
signature = sig.r + sig.s + "01";
headers = {
"content-type": "application/json;charset=utf-8",
"authorization": `${this.getStorage('token').token_type} ${this.getStorage('token').access_token}`,
"origin": "https://www.aliyundrive.com",
"referer": "https://www.aliyundrive.com/",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.41",
"x-canary": "client=web,app=adrive,version=v3.17.0",
"x-device-id": device_id,
"x-signature": signature,
}
//create session
const req = await fetch('https://api.aliyundrive.com/users/v1/users/device/create_session', {
method: 'POST',
body: JSON.stringify({ "deviceName": "Edge浏览器", "modelName": "Windows网页版", "pubKey": publicKey }),
headers: headers
});
const res = await req.json();
console.log("create session",res);
},
init() {
main.initDefaultConfig();
main.initECDSAKey();
//识别页面类型
let sharepage=window.location.href.indexOf("s/")>0;
//劫持XMLHttpRequest
var send = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function (data) {
let url = this.openParams ? this.openParams[1] : this.responseURL;
//console.log("aopsend",data)
if (url.indexOf("/file/get_video_preview_play_info") > 0) {
//console.log("inject",data)
g_drive_id = JSON.parse(data).drive_id;
g_file_id = JSON.parse(data).file_id;
g_share_id = JSON.parse(data).share_id;
if (sharepage) {
g_file_name = document.getElementsByClassName("header-file-name--CN_fq")[0].textContent;
}
else {
g_file_name = document.getElementsByClassName("text--2KGvI")[0].textContent;
}
//console.log("got:", url, g_drive_id, g_file_id, g_file_name);
//循环检测dom创建,添加按钮
let ins = setInterval(() => {
let quality = document.getElementsByClassName("drawer-list--JYzyI");
if (quality.length > 0) {
if (sharepage) {
quality[0].innerHTML += `<li class="drawer-item--2cNtQ original-video-play" data-is-current="false">
<div class="text--AMJbu">原画下载</div>
</li>`;
let play_button = document.getElementsByClassName("original-video-play")[0];
play_button.addEventListener("click", async function () {
let url = await main.getPCSLink(g_file_id, g_share_id);
let d = document.createElement("a");
d.download = g_file_name;
d.rel = "noopener";
d.href = url;
d.dispatchEvent(new MouseEvent("click"));
});
}
else {
quality[2].innerHTML += `<li class="drawer-item--2cNtQ original-video-play" data-is-current="false">
<div class="text--AMJbu">原画播放</div>
</li>`;
let play_button = document.getElementsByClassName("original-video-play")[0];
play_button.addEventListener("click", async function () {
let url = await main.getRealLink(g_drive_id, g_file_id);
let scheme = GM_getValue('url-scheme');
url = scheme + url;
let d = document.createElement("a");
d.download = g_file_name;
d.rel = "noopener";
d.href = url;
d.dispatchEvent(new MouseEvent("click"));
});
}
clearInterval(ins);
}
}, 50);
}
send.apply(this, arguments);
};
}
};
main.init();
})();