// ==UserScript== // @name 阿里云盘 // @namespace https://scriptcat.org/zh-CN/users/13895 // @version 5.1.1 // @description 让视频播放变成我想要的那个样子 // @author You // @match https://www.alipan.com/* // @match https://www.aliyundrive.com/* // @connect alipan.com // @connect aliyundrive.com // @require https://scriptcat.org/lib/950/^1.0.1/Joysound.js // @require https://scriptcat.org/lib/2163/^1.0.0/alipanThirdParty.js // @require https://scriptcat.org/lib/2164/^1.0.3/alipanArtPlugins.js // @require https://unpkg.com/hls.js@1.5.15/dist/hls.min.js // @require https://unpkg.com/artplayer@5.2.3/dist/artplayer.js // @require https://unpkg.com/leancloud-storage@4.15.2/dist/av-min.js // @require https://unpkg.com/m3u8-parser@7.2.0/dist/m3u8-parser.min.js // @icon https://gw.alicdn.com/imgextra/i3/O1CN01aj9rdD1GS0E8io11t_!!6000000000620-73-tps-16-16.ico // @antifeature ads // @antifeature membership // @antifeature payment // @antifeature referral-link // @antifeature tracking // @run-at document-start // @grant unsafeWindow // @grant GM_xmlhttpRequest // @grant GM_download // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // ==/UserScript== (function() { 'use strict'; var obj = { file_page: { root_info: {}, send_params: {}, file_items: [] }, video_page: { video_info: {}, video_file: {}, video_items: [], subtitle_items: [] } }; obj.httpListener = function () { (function(send) { XMLHttpRequest.prototype.send = function (sendParams) { this.addEventListener("load", function(event) { if (this.readyState == 4 && this.status == 200) { var response = this.response || this.responseText || "", responseURL = this.responseURL; if (responseURL.indexOf("/file/list") > 0 || responseURL.indexOf("/file/search") > 0) { obj.initFilesInfo(sendParams, response); } else if (responseURL.indexOf("/file/get_video_preview_play_info") > 0) { obj.initVideoPlayInfo(response); obj.initVideoPlayer(); } } }, false); send.apply(this, arguments); }; })(XMLHttpRequest.prototype.send); }; obj.initFilesInfo = function (sendParams, response) { const { send_params, } = obj.file_page; try { sendParams = JSON.parse(sendParams) } catch (error) { }; try { response = JSON.parse(response) } catch (error) { }; if (sendParams instanceof Object && response instanceof Object) { const { order_by, order_direction, parent_file_id } = sendParams || {}; if (!(order_by === send_params.order_by && order_direction === send_params.order_direction && parent_file_id === send_params.parent_file_id)) { obj.file_page.file_items = []; } obj.file_page.send_params = sendParams; obj.file_page.file_items.find((item) => item?.file_id === response.items[0]?.file_id) || (obj.file_page.file_items = obj.file_page.file_items.concat(response.items)); obj.showTipSuccess("文件列表获取完成 共:" + obj.file_page.file_items.length + "项"); if (obj.file_page.file_items.length) { // obj.isHomePage() ? obj.initDownloadHomePage() : obj.initDownloadSharePage; } } }; obj.initVideoPlayInfo = function (response) { try { response = JSON.parse(response) } catch (error) { }; if (response instanceof Object) { obj.video_page.video_info = response; obj.video_page.video_items = obj.file_page.file_items.filter(function (item, index) { return item.type == "file" && item.category == "video"; }); obj.video_page.video_file = obj.file_page.file_items.find(function (item, index) { return item.type == "file" && item.file_id == response.file_id; }); obj.video_page.subtitle_items = obj.file_page.file_items.filter(function (item, index) { return item.type == "file" && item.category === "others" && ["vtt", "srt", "ass", "ssa"].includes(item.file_extension.toLowerCase()); }); } }; obj.initVideoPlayer = function () { obj.getVideoPreviewPlayInfo().then((response) => { Object.assign(obj.video_page.video_info, response); obj.replaceVideoPlayer().then(() => { const options = Object.assign({}, obj.video_page); window.alipanArtPlugins.init(options).then((art) => { art.once('ready', function () { obj.getSublistByPan().then(function (sublist) { sublist.length && art.emit('sublist', sublist); }); }); art.on('resume', (fileOption) => { obj.video_page.video_file = fileOption; obj.getVideoPreviewPlayInfo().then((response) => { art.emit('resumeed', response); }); }); art.on('reload', (fileOption) => { obj.video_page.video_file = fileOption; obj.getVideoPreviewPlayInfo().then((response) => { art.emit('reloaded', response); const filenameNode = document.querySelector("[class^=header-file-name], [class^=filename] span, [class^=header-center] div span"); if (filenameNode) { filenameNode.innerText = fileOption.name; } obj.getSublistByPan().then(function (sublist) { sublist.length && art.emit('sublist', sublist); }); }); }); const closeNode = document.querySelector('[class^="header-"] [data-icon-type="PDSClose"], [class^="header-"] [data-icon-type="PDSChevronLeft"]'); closeNode && closeNode.addEventListener('click', function () { art.destroy(); }, { once: true }); }); }); }); }; obj.replaceVideoPlayer = function () { var container, videoNode = document.querySelector("video"); if (videoNode) { container = document.getElementById("artplayer"); if (container) { return Promise.resolve(); } container = document.createElement("div"); container.setAttribute("id", "artplayer"); container.setAttribute("style", "width: 100%; height: 100%;"); var videoParentNode = videoNode.parentNode.parentNode; videoParentNode.parentNode.replaceChild(container, videoParentNode); return Promise.resolve(); } else { obj.showTipLoading("正在替换视频播放器 ...", 1e3); return obj.delay().then(function () { return obj.replaceVideoPlayer(); }); } }; obj.getVideoPreviewPlayInfo = function () { return window.alipanThirdParty.getVipInfo().then((info) => { const { thirdPartyVip, thirdPartyVipExpire } = info || {}; if (thirdPartyVip) { return obj.getVideoPreviewPlayInfoThirdParty(); } else { return Promise.reject(); } }).catch(() => { return obj.getVideoPreviewPlayInfoWeb(); }); }; obj.getVideoPreviewPlayInfoThirdParty = function () { const { drive_id, file_id, share_id } = obj.video_page.video_file || obj.video_page.video_info; if (share_id) { return obj.saveFile(file_id, share_id).then((response) => { const { responses: [{ body, status }] } = response; if (status === 201) { const { drive_id, file_id } = body; return window.alipanThirdParty.getVideoPreviewPlayInfo(drive_id, file_id).finally(() => { window.alipanThirdParty.delete(drive_id, file_id); }); } else { obj.showTipError("文件缓存失败,可能网盘存储空间已满 ...", 5e3); return Promise.reject(); } }); } return window.alipanThirdParty.getVideoPreviewPlayInfo(drive_id, file_id); }; obj.getVideoPreviewPlayInfoWeb = function () { return obj.refresh().then (() => { const { drive_id, file_id, share_id } = obj.video_page.video_file || obj.video_page.video_info; if (share_id) { return obj.saveFile(file_id, share_id).then((response) => { const { responses: [{ body, status }] } = response; if (status === 201) { const { drive_id, file_id } = body; return obj.get_video_preview_play_info(drive_id, file_id).finally(() => { obj.deleteFile(drive_id, file_id); }); } else { obj.showTipError("文件缓存失败,可能网盘存储空间已满 ...", 5e3); return Promise.reject(); } }); } return obj.get_video_preview_play_info(drive_id, file_id); }); }; obj.get_video_preview_play_info = function (drive_id, file_id) { const { token_type, access_token } = obj.getItem("token"); return fetch("https://api.aliyundrive.com/v2/file/get_video_preview_play_info", { body: JSON.stringify({ category: "live_transcoding", drive_id: drive_id, file_id: file_id, template_id: "", get_subtitle_info: !0, mode: "high_res", url_expire_sec: 14400 }), headers: { "authorization": "".concat(token_type || "", " ").concat(access_token || ""), "content-type": "application/json;charset=UTF-8", }, method: "POST" }).then((response) => { return response.ok ? response.json() : Promise.reject(); }); }; obj.getSublistByPan = function () { const filelist = obj.filterSubFilesByPan(); if (filelist.length) { return obj.getDownloadUrlBatch(filelist).then(function (filelist) { const sublist = filelist.map(function (item, index) { return { html: `内挂字幕「${item.file_extension}」`, name: item.name, url: item.url, type: item.file_extension }; }); return sublist; }); } return Promise.resolve([]); }; obj.filterSubFilesByPan = function () { const { video_file, subtitle_items, video_items } = obj.video_page; if (!subtitle_items.length) return []; if (video_items.length === 1) return subtitle_items; const getBaseName = (fileName) => fileName.split('.').slice(0, -1).join('.').toLowerCase(); const subItems = subtitle_items.map(item => ({ item, base: getBaseName(item.name) })); const videoBase = getBaseName(video_file.name); const videoVariants = []; let currentVariant = videoBase; while (currentVariant) { videoVariants.push(currentVariant); currentVariant = currentVariant.split('.').slice(0, -1).join('.'); } for (const variant of videoVariants) { const matched = subItems.filter(({ base }) => base.includes(variant) || variant.includes(base)); if (matched.length) return matched.map(({ item }) => item); } return []; }; obj.getDownloadUrlBatch = function (fileList) { if (!Array.isArray(fileList)) { fileList = [fileList]; } var promises = fileList.map(function (item) { return item.type == "file" && obj.getDownloadUrl(item).then((response) => { item.url = response.url; return item; }); }).filter(Boolean); return Promise.allSettled(promises).then((results) => { return fileList; }); }; obj.getDownloadUrl = function (file) { return obj.refresh().then (() => { const { drive_id, file_id, share_id } = file; if (share_id) { return obj.saveFile(file_id, share_id).then((response) => { const { responses: [{ body, status }] } = response; if (status === 201) { const { drive_id, file_id } = body; return obj.get_download_url(drive_id, file_id).finally(() => { obj.deleteFile(drive_id, file_id); }); } else { obj.showTipError("文件缓存失败,请自行清理网盘文件后重试。。。", 10e3); return Promise.reject(); } }); } return obj.get_download_url(drive_id, file_id); }); }; obj.get_download_url = function (drive_id, file_id) { const { token_type, access_token } = obj.getItem("token"); return fetch("https://api.aliyundrive.com/v2/file/get_download_url", { body: JSON.stringify({ expire_sec: 14400, drive_id: drive_id, file_id: file_id }), headers: { "authorization": "".concat(token_type || "", " ").concat(access_token || ""), "content-type": "application/json;charset=UTF-8", "x-canary": "client=windows,app=adrive,version=v6.0.0", }, method: "POST" }).then((response) => { return response.ok ? response.json() : Promise.reject(); }); }; obj.saveFile = function (file_id, share_id) { const { token_type, access_token, default_drive_id } = obj.getItem("token"); const { share_token } = obj.getItem("shareToken"); return fetch("https://api.aliyundrive.com/adrive/v4/batch", { body: JSON.stringify({ requests: [ { body: { auto_rename: true, file_id: file_id, share_id: share_id, to_parent_file_id: "root", to_drive_id: default_drive_id }, headers: { "Content-Type": "application/json" }, id: "0", method: "POST", url: "/file/copy" } ], resource: "file" }), headers: { "authorization": "".concat(token_type || "", " ").concat(access_token || ""), "content-type": "application/json;charset=UTF-8", "x-share-token": share_token }, method: "POST" }).then((response) => { return response.ok ? response.json() : Promise.reject(); }); }; obj.deleteFile = function (drive_id, file_id) { const { token_type, access_token } = obj.getItem("token"); return fetch("https://api.aliyundrive.com/v3/file/delete", { body: JSON.stringify({ drive_id: drive_id, file_id: file_id }), headers: { "authorization": "".concat(token_type || "", " ").concat(access_token || ""), "content-type": "application/json;charset=UTF-8", }, method: "POST" }); }; obj.refresh = function () { const token = obj.getItem("token") || {}; if (obj.tokenExpires(token)) { return Promise.resolve(); } return fetch("https://api.aliyundrive.com/token/refresh", { body: JSON.stringify({ refresh_token: token.refresh_token }), headers: { "accept": "application/json, text/plain, */*", "content-type": "application/json", }, method: "POST" }).then((response) => { return response.ok ? response.json() : Promise.reject(); }).then((response) => { obj.setItem("token", response); return response; }); }; obj.tokenExpires = function (file) { var t = file.expire_time, i = Number(file.expires_in), e = Date.parse(t) - Date.now(); if (0 < e && e < 1e3 * i) return !0; return !1; }; obj.getItem = function (n) { n = localStorage.getItem(n); if (!n) return null; try { return JSON.parse(n); } catch (e) { return n; } }; obj.setItem = function (n, t) { n && t != undefined && localStorage.setItem(n, t instanceof Object ? JSON.stringify(t) : t); }; obj.removeItem = function (n) { n != undefined && localStorage.removeItem(n); }; obj.isSharePage = function () { return location.href.indexOf("aliyundrive.com/s/") > 0 || location.href.indexOf("alipan.com/s/") > 0; }; obj.delay = function (ms = 500) { return new Promise(resolve => setTimeout(resolve, ms)); }; obj.showTipSuccess = function (message, time) { obj.showNotify({ type: "success", message: message, time: time }); }; obj.showTipError = function (message, time) { obj.showNotify({ type: "fail", message: message, time: time }); }; obj.showTipLoading = function (message, time) { obj.showNotify({ type: "loading", message: message, time: time }); }; obj.showNotify = function (opts) { if (unsafeWindow.application) { unsafeWindow.application.showNotify(opts); } else { var css = [ ".notify{display:none;position:absolute;top:0;left:25%;width:50%;text-align:center;overflow:hidden;z-index:1010}", ".notify .alert{display:inline-block;*display:inline;*zoom:1;min-width:110px;white-space:nowrap}", ".alert-success,.alert-fail,.alert-loading{padding:0 20px;line-height:34px;font-size:14px;color:#ffffff}", ".alert-success,.alert-loading{background:#36be63}", ".alert-fail{background:#ff794a}", ".fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}", ".fade.in{opacity:1}" ]; var style = document.createElement('style'); style.textContent = css.join(" "); (document.head || document.documentElement).appendChild(style); var notifyDiv = document.createElement('div'); notifyDiv.id = 'J_Notify'; notifyDiv.className = 'notify'; notifyDiv.style.cssText = 'width: 650px; margin: 10px auto; display: none;'; document.body.appendChild(notifyDiv); unsafeWindow.application = { notifySets: { type_class_obj: {success: "alert-success", fail: "alert-fail", loading: "alert-loading"}, count: 0, delay: 3e3 }, showNotify: function(opts) { var that = this, class_obj = that.notifySets.type_class_obj, count = that.notifySets.count, notifyEl = document.getElementById('J_Notify'), alertEl; if (opts.type == "loading") { that.notifySets.delay *= 5; } if (!notifyEl.querySelector('.alert')) { notifyEl.innerHTML = '
'; notifyEl.style.display = 'block'; } else { Object.keys(class_obj).forEach(function(key) { notifyEl.classList.remove(class_obj[key]); }); } alertEl = notifyEl.querySelector('.alert'); alertEl.textContent = opts.message; alertEl.classList.add(class_obj[opts.type]); that.notifySets.count += 1; var delay = opts.time || that.notifySets.delay; setTimeout(function() { if (++count == that.notifySets.count) { that.hideNotify(); } }, delay); }, hideNotify: function() { var notifyEl = document.getElementById('J_Notify'); notifyEl.innerHTML = ''; notifyEl.style.display = 'none'; } }; obj.showNotify(opts); } }; obj.hideNotify = function () { if (unsafeWindow.application) { unsafeWindow.application.hideNotify(); } }; obj.run = function () { obj.httpListener(); }(); console.log("=== 阿里云盘 好棒棒!==="); // Your code here... })();