阿里云盘Dplayer

支持生成文件下载链接(多种下载姿势),支持第三方播放器DPlayer(支持自动/手动添加字幕,突破视频2分钟限制,选集,上下集,自动记忆播放,跳过片头片尾, 字幕设置随心所欲...),支持自定义分享密码,支持图片预览,支持移动端播放,...

  1. // ==UserScript==
  2. // @license MIT
  3. // @name 阿里云盘Dplayer
  4. // @namespace http://tampermonkey.net/
  5. // @version 3.1.1
  6. // @description 支持生成文件下载链接(多种下载姿势),支持第三方播放器DPlayer(支持自动/手动添加字幕,突破视频2分钟限制,选集,上下集,自动记忆播放,跳过片头片尾, 字幕设置随心所欲...),支持自定义分享密码,支持图片预览,支持移动端播放,...
  7. // @author You
  8. // @match https://www.aliyundrive.com/*
  9. // @connect lc-cn-n1-shared.com
  10. // @connect *
  11. // @icon https://gw.alicdn.com/imgextra/i3/O1CN01aj9rdD1GS0E8io11t_!!6000000000620-73-tps-16-16.ico
  12. // @require https://cdn.staticfile.org/localforage/1.10.0/localforage.min.js
  13. // @require https://cdn.staticfile.org/jquery/3.6.0/jquery.min.js
  14. // @antifeature ads
  15. // @antifeature membership
  16. // @antifeature payment
  17. // @antifeature referral-link
  18. // @antifeature tracking
  19. // @run-at document-body
  20. // @grant unsafeWindow
  21. // @grant GM_xmlhttpRequest
  22. // @grant GM_getValue
  23. // @grant GM_setValue
  24. // ==/UserScript==
  25.  
  26. (function() {
  27. 'use strict';
  28.  
  29. var localforage = window.localforage;
  30. var $ = $ || window.$;
  31. var obj = {
  32. file_page: {
  33. parent_file_id: "root",
  34. file_info: {},
  35. order_by: "",
  36. order_direction: "",
  37. next_marker_list: [],
  38. items: []
  39. },
  40. video_page: {
  41. play_info: {},
  42. sub_info: {
  43. index: 0
  44. },
  45. elevideo: "",
  46. player: null,
  47. media_num: 0
  48. }
  49. };
  50.  
  51. obj.useDPlayer = function () {
  52. obj.dPlayerSupport(function (result) {
  53. result && obj.dPlayerStart();
  54. });
  55. };
  56.  
  57. obj.dPlayerSupport = function (callback) {
  58. (function laodcdn(urlArr, index) {
  59. var arr = urlArr[index];
  60. if (arr) {
  61. var promises = [];
  62. arr.forEach(function (url, index) {
  63. promises.push(loadScript(url));
  64. });
  65. Promise.all(promises).then(function(results) {
  66. setTimeout(function () {
  67. obj.isAppreciation.toString().length == 1367 && callback(unsafeWindow.DPlayer);
  68. }, 0);
  69. }).catch(function (error) {
  70. laodcdn(urlArr, ++index);
  71. });
  72. }
  73. else {
  74. callback && callback(unsafeWindow.DPlayer);
  75. }
  76. })([
  77. [
  78. "https://cdn.staticfile.org/hls.js/1.3.2/hls.min.js",
  79. "https://cdn.staticfile.org/dplayer/1.27.1/DPlayer.min.js",
  80. ],
  81. [
  82. "https://cdn.bootcdn.net/ajax/libs/hls.js/1.3.2/hls.min.js",
  83. "https://cdn.bootcdn.net/ajax/libs/dplayer/1.27.1/DPlayer.min.js",
  84. ],
  85. [
  86. "https://cdn.jsdelivr.net/npm/hls.js/dist/hls.min.js",
  87. "https://cdn.jsdelivr.net/npm/dplayer/dist/DPlayer.min.js",
  88. ],
  89. ], 0);
  90. function loadScript (src) {
  91. if (!window.instances) {
  92. window.instances = {};
  93. }
  94. if (!window.instances[src]) {
  95. window.instances[src] = new Promise((resolve, reject) => {
  96. const script = document.createElement("script")
  97. script.src = src;
  98. script.type = "text/javascript";
  99. script.onload = resolve;
  100. script.onerror = reject;
  101. document.head.appendChild(script);
  102. });
  103. }
  104. return window.instances[src];
  105. }
  106. };
  107.  
  108. obj.dPlayerStart = function () {
  109. var prevPlayer = obj.video_page.player;
  110. var dPlayerNode, videoNode = document.querySelector("video");
  111. if (videoNode) {
  112. dPlayerNode = document.getElementById("dplayer");
  113. if (!dPlayerNode) {
  114. dPlayerNode = document.createElement("div");
  115. dPlayerNode.setAttribute("id", "dplayer");
  116. dPlayerNode.setAttribute("style", "width: 100%; height: 100%;");
  117. var videoParentNode = videoNode.parentNode.parentNode;
  118. obj.video_page.elevideo = videoParentNode.parentNode.replaceChild(dPlayerNode, videoParentNode);
  119. }
  120. }
  121. else {
  122. return setTimeout(obj.dPlayerStart, 500);
  123. }
  124. var quality = [], defaultQuality, localQuality = localStorage.getItem("dplayer-quality");;
  125. var play_info = obj.video_page.play_info || {};
  126. var video_preview_play_info = play_info.video_preview_play_info || {};
  127. var task_list = video_preview_play_info.live_transcoding_task_list;
  128. if (Array.isArray(task_list)) {
  129. var pds = {
  130. UHD: "4K 超清",
  131. QHD: "2K 超清",
  132. FHD: "1080 全高清",
  133. HD: "720 高清",
  134. SD: "540 标清",
  135. LD: "360 流畅"
  136. };
  137. task_list.forEach(function (item, index) {
  138. var name = pds[item.template_id];
  139. localQuality ? localQuality == name ? defaultQuality = index : defaultQuality = index : defaultQuality = index;
  140. quality.push({
  141. name: name,
  142. url: item.url || item.preview_url,
  143. type: "hls"
  144. });
  145. });
  146. }
  147. else {
  148. obj.showTipError("获取播放信息失败:请刷新网页重试");
  149. return;
  150. }
  151. if (obj.video_page.file_id === play_info.file_id) {
  152. if (prevPlayer && document.querySelector("video")) {
  153. return obj.dPlayerThrough(quality);
  154. }
  155. }
  156. else {
  157. obj.video_page.file_id = play_info.file_id;
  158. if (prevPlayer) {
  159. prevPlayer.destroy();
  160. prevPlayer = null;
  161. }
  162. }
  163. var options = {
  164. container: dPlayerNode,
  165. video: {
  166. quality: quality,
  167. defaultQuality: defaultQuality,
  168. customType: {
  169. hls: function (video, player) {
  170. if (player.plugins.hls) {
  171. player.plugins.prevHls = player.plugins.hls;
  172. delete player.plugins.hls;
  173. }
  174. const hls = new unsafeWindow.Hls();
  175. player.plugins.hls = hls;
  176. hls.loadSource(video.src);
  177. hls.attachMedia(video);
  178. }
  179. }
  180. },
  181. subtitle: {
  182. url: "",
  183. type: "webvtt",
  184. fontSize: (localStorage.getItem("dplayer-subtitle-fontSize") || 5) + "vh",
  185. bottom: (localStorage.getItem("dplayer-subtitle-bottom") || 10) + "%",
  186. color: localStorage.getItem("dplayer-subtitle-color") || "#ffd821",
  187. },
  188. autoplay: true,
  189. screenshot: true,
  190. hotkey: false,
  191. airplay: true,
  192. volume: 1.0,
  193. playbackSpeed: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 3, 4],
  194. contextmenu: [
  195. {
  196. text: "👍 爱发电 不再弹出 👍",
  197. link: "https://afdian.net/order/create?plan_id=be4f4d0a972811eda14a5254001e7c00",
  198. click: obj.showDialog
  199. }
  200. ],
  201. theme: obj.getRandomColor()
  202. };
  203. try {
  204. var player = obj.video_page.player = new unsafeWindow.DPlayer(options);
  205. if (prevPlayer) {
  206. const { video } = prevPlayer;
  207. player.seek(video.currentTime - 1);
  208. player.speed(video.playbackRate);
  209. player.video.muted = video.muted;
  210. prevPlayer.destroy();
  211. prevPlayer = null;
  212. }
  213. obj.playerReady(player, function(player) {
  214. player.options.hotkey || obj.dPlayerHotkey();
  215. obj.dPlayerInitAspectRatio();
  216. obj.autoSkipPlayNext();
  217. obj.memoryPlay();
  218. obj.playSetting();
  219. obj.selectEpisode();
  220. obj.addCueVideoSubtitle(function (textTracks) {
  221. if (textTracks) {
  222. obj.selectSubtitles(textTracks);
  223. obj.dPlayerSubtitleStyle();
  224. }
  225. });
  226. player.on("quality_end", function () {
  227. localStorage.setItem("dplayer-quality", player.quality.name);
  228. obj.addCueVideoSubtitle();
  229. });
  230. player.speed(localStorage.getItem("dplayer-speed") || 1);
  231. player.on("ratechange", function () {
  232. player.notice("播放速度:" + player.video.playbackRate);
  233. localStorage.getItem("dplayer-speed") == player.video.playbackRate || localStorage.setItem("dplayer-speed", player.video.playbackRate);
  234. });
  235. player.on("contextmenu_hide", function () {
  236. obj.isAppreciation(function (data) {
  237. data || player.contextmenu.show(player.container.offsetWidth / 2.5, player.container.offsetHeight / 3);
  238. });
  239. });
  240. localStorage.getItem("dplayer-isfullscreen") == "true" && player.fullScreen.request("browser");
  241. player.on("fullscreen", function () {
  242. localStorage.setItem("dplayer-isfullscreen", true);
  243. try {
  244. screen.orientation.lock("landscape");
  245. } catch (error) { };
  246. });
  247. player.on("fullscreen_cancel", function () {
  248. localStorage.removeItem("dplayer-isfullscreen");
  249. try {
  250. screen.orientation.unlock();
  251. } catch (error) { };
  252. });
  253. });
  254. } catch (error) {
  255. console.error("播放器创建失败", error);
  256. }
  257. };
  258.  
  259. obj.dPlayerThrough = function (quality) {
  260. var player = obj.video_page.player;
  261. player.options.video.quality = quality;
  262. player.quality = player.options.video.quality[ player.qualityIndex ];
  263. const paused = player.video.paused;
  264. const videoHTML = '<video class="dplayer-video" webkit-playsinline playsinline crossorigin="anonymous" preload="auto" src="' + player.quality.url + '"><track kind="metadata" default src=""></track></video>';
  265. const videoEle = new DOMParser().parseFromString(videoHTML, 'text/html').body.firstChild;
  266. player.template.videoWrap.insertBefore(videoEle, player.template.videoWrap.getElementsByTagName('div')[0]);
  267. player.prevVideo = player.video;
  268. player.video = videoEle;
  269. player.initVideo(player.video, player.quality.type || player.options.video.type);
  270. player.video.currentTime = player.prevVideo.currentTime + 1;
  271. player.on('canplaythrough', () => {
  272. if (player.prevVideo) {
  273. if (player.video.currentTime !== player.prevVideo.currentTime) {
  274. player.video.currentTime = player.prevVideo.currentTime;
  275. (obj.onPost.length && obj.onPost.toString().length == 460) || player.destroy();
  276. }
  277. player.prevVideo.muted && (player.video.muted = player.prevVideo.muted);
  278. player.prevVideo.pause();
  279. player.template.videoWrap.removeChild(player.prevVideo);
  280. player.video.classList.add('dplayer-video-current');
  281. player.template.video = player.video;
  282. if (!paused) {
  283. const bezelswitch = player.bezel.switch;
  284. player.bezel.switch = () => {};
  285. setTimeout(() => { player.bezel.switch = bezelswitch; }, 1000);
  286. player.video.play();
  287. player.controller.hide();
  288. setTimeout(() => {
  289. obj.isAppreciation(function (data) {
  290. data || player.contextmenu.show(player.container.offsetWidth / 2.5, player.container.offsetHeight / 3);
  291. });
  292. document.querySelectorAll("video").length > 1 && [ ... document.querySelectorAll("video") ].forEach(element => {
  293. element.paused && player.template.videoWrap.removeChild(element);
  294. });
  295. });
  296. }
  297. setTimeout(() => {
  298. player.controller.hide();
  299. if (player.plugins.prevHls) {
  300. player.plugins.prevHls.destroy();
  301. delete player.plugins.prevHls;
  302. }
  303. });
  304. player.prevVideo = null;
  305. obj.dPlayerEvents(player);
  306. }
  307. });
  308. };
  309.  
  310. obj.dPlayerEvents = function (player) {
  311. obj.playerReady(player, function(player) {
  312. const { options: { contextmenu } } = player;
  313. JSON.stringify(contextmenu).includes(5254001) || player.destroy();
  314. obj.dPlayerAspectRatio();
  315. obj.addCueVideoSubtitle(function (textTracks) {
  316. if (textTracks) {
  317. obj.selectSubtitles(textTracks);
  318. obj.dPlayerSubtitleStyle();
  319. obj.offsetCache && obj.dPlayerSubtitleOffset();
  320. }
  321. });
  322. });
  323. };
  324.  
  325. obj.playerReady = function (player, callback) {
  326. if (player.isReady) {
  327. callback && callback(player);
  328. }
  329. else if (player.video.duration > 0 || player.video.readyState > 2) {
  330. player.isReady = true;
  331. callback && callback(player);
  332. }
  333. else {
  334. player.video.ondurationchange = function () {
  335. player.video.ondurationchange = null;
  336. player.isReady = true;
  337. callback && callback(player);
  338. }
  339. }
  340. };
  341.  
  342. obj.dPlayerHotkey = function () {
  343. if (window.dPlayerHotkey) return;
  344. window.dPlayerHotkey = true;
  345. document.addEventListener("keydown", (function(e) {
  346. var t = obj.video_page.player;
  347. if (t && document.getElementById("dplayer")) {
  348. var a = document.activeElement.tagName.toUpperCase()
  349. , n = document.activeElement.getAttribute("contenteditable");
  350. if ("INPUT" !== a && "TEXTAREA" !== a && "" !== n && "true" !== n) {
  351. var o, r = e || window.event;
  352. switch (r.keyCode) {
  353. case 13:
  354. r.preventDefault();
  355. t.fullScreen.toggle();
  356. break;
  357. case 32:
  358. r.preventDefault();
  359. t.toggle();
  360. break;
  361. case 37:
  362. r.preventDefault();
  363. t.seek(t.video.currentTime - 5);
  364. break;
  365. case 39:
  366. r.preventDefault();
  367. t.seek(t.video.currentTime + 5);
  368. break;
  369. case 38:
  370. r.preventDefault();
  371. o = t.volume() + .01;
  372. t.volume(o);
  373. break;
  374. case 40:
  375. r.preventDefault();
  376. o = t.volume() - .01;
  377. t.volume(o);
  378. break;
  379. case 36:
  380. r.preventDefault();
  381. t.notice("上一项");
  382. o = document.querySelector("[data-icon-type=PDSChevronLeft]") || document.querySelector("[data-icon-type=PDSLeftNormal]");
  383. o && o.click();
  384. break;
  385. case 35:
  386. r.preventDefault();
  387. t.notice("下一项");
  388. o = document.querySelector("[data-icon-type=PDSChevronRight]") || document.querySelector("[data-icon-type=PDSRightNormal]");
  389. o && o.click();
  390. break;
  391. }
  392. }
  393. }
  394. }));
  395. document.addEventListener("wheel", function (event) {
  396. event = event || window.event;
  397. if ($(event.target).closest(".playlist-content").length) return;
  398. var o, t = obj.video_page.player;
  399. if (event.deltaY < 0) {
  400. o = t.volume() + .01;
  401. t.volume(o);
  402. } else if (event.deltaY > 0) {
  403. o = t.volume() - .01;
  404. t.volume(o);
  405. }
  406. });
  407. };
  408.  
  409. obj.dPlayerInitAspectRatio = function () {
  410. if ($(".dplayer-icons-right .btn-select-aspectRatio").length) return;
  411. var html = '<div class="dplayer-quality btn-select-aspectRatio"><button class="dplayer-icon dplayer-quality-icon">画面比例</button><div class="dplayer-quality-mask"><div class="dplayer-quality-list">';
  412. html += '<div class="dplayer-quality-item" data-value="4:3">4:3</div><div class="dplayer-quality-item" data-value="16:9">16:9</div><div class="dplayer-quality-item" data-value="none">原始比例</div><div class="dplayer-quality-item" data-value="cover">自动裁剪</div><div class="dplayer-quality-item" data-value="fill">拉伸填充</div><div class="dplayer-quality-item" data-value="default">系统默认</div>';
  413. html += '</div></div></div>';
  414. $(".dplayer-icons-right").prepend(html);
  415. $(".btn-select-aspectRatio .dplayer-quality-item").on("click", function() {
  416. var ratio = $(this).attr("data-value");
  417. obj.dPlayerAspectRatio(ratio);
  418. });
  419. };
  420.  
  421. obj.dPlayerAspectRatio = function (ratio) {
  422. const player = obj.video_page.player;
  423. const { template: { videoWrap, video } } = player;
  424. const ratios = { "default": "系统默认", "4:3": "4:3", "16:9": "16:9", "fill": "拉伸填充", "cover": "自动裁剪", "none": "原始比例" };
  425. !ratio ? (ratio = videoWrap.dataset.aspectRatio || "default") : player.notice(`画面比例: ${ratios[ratio]}`);
  426. if (ratio === "default") {
  427. setStyle(video, 'width', null);
  428. setStyle(video, 'height', null);
  429. setStyle(video, 'padding', null);
  430. setStyle(video, 'object-fit', null);
  431. delete videoWrap.dataset.aspectRatio;
  432. }
  433. else if (["4:3", "16:9"].includes(ratio)) {
  434. const ratioArray = ratio.split(':').map(Number);
  435. const { videoWidth, videoHeight } = video;
  436. const { clientWidth, clientHeight } = videoWrap;
  437. const videoRatio = videoWidth / videoHeight;
  438. const setupRatio = ratioArray[0] / ratioArray[1];
  439. if (videoRatio > setupRatio) {
  440. const percentage = (setupRatio * videoHeight) / videoWidth;
  441. setStyle(video, 'width', `${percentage * 100}%`);
  442. setStyle(video, 'height', '100%');
  443. setStyle(video, 'padding', `0 ${(clientWidth - clientWidth * percentage) / 2}px`);
  444. } else {
  445. const percentage = videoWidth / setupRatio / videoHeight;
  446. setStyle(video, 'width', '100%');
  447. setStyle(video, 'height', `${percentage * 100}%`);
  448. setStyle(video, 'padding', `${(clientHeight - clientHeight * percentage) / 2}px 0`);
  449. }
  450. setStyle(video, 'object-fit', 'fill');
  451. videoWrap.dataset.aspectRatio = ratio;
  452. }
  453. else if (["fill", "cover", "none"].includes(ratio)) {
  454. setStyle(video, 'width', null);
  455. setStyle(video, 'height', null);
  456. setStyle(video, 'padding', null);
  457. setStyle(video, 'object-fit', ratio);
  458. videoWrap.dataset.aspectRatio = ratio;
  459. }
  460. function setStyle (element, key, value) {
  461. element.style[key] = value;
  462. return element;
  463. }
  464. };
  465.  
  466. obj.memoryPlay = function () {
  467. if (obj.hasMemoryDisplay) return;
  468. obj.hasMemoryDisplay = true;
  469. var jumpstart = obj.getPlayMemory("jumpstart") || 60;
  470. var jumpend = obj.getPlayMemory("jumpend") || 120;
  471. var skipPosition = obj.getPlayMemory("skipposition");
  472. var player = obj.video_page.player;
  473. var playInfo = obj.video_page.play_info;
  474. var fileList = obj.file_page.items
  475. , file = fileList.find(function (item, index) {
  476. return item.file_id == playInfo.file_id;
  477. })
  478. , sign = file ? file.file_id : ""
  479. , memoryTime = obj.getPlayMemory(sign);
  480. if (memoryTime && parseInt(memoryTime)) {
  481. var autoPosition = obj.getItem("dplayer-position");
  482. if (autoPosition) {
  483. player.seek(memoryTime - 1);
  484. }
  485. else {
  486. var formatTime = formatVideoTime(memoryTime);
  487. $(player.container).append('<div class="memory-play-wrap" style="display: block;position: absolute;left: 33px;bottom: 66px;font-size: 15px;padding: 7px;border-radius: 3px;color: #fff;z-index:100;background: rgba(0,0,0,.5);">上次播放到:' + formatTime + '&nbsp;&nbsp;<a href="javascript:void(0);" class="play-jump" style="text-decoration: none;color: #06c;"> 跳转播放 &nbsp;</a><em class="close-btn" style="display: inline-block;width: 15px;height: 15px;vertical-align: middle;cursor: pointer;background: url(https://nd-static.bdstatic.com/m-static/disk-share/widget/pageModule/share-file-main/fileType/video/img/video-flash-closebtn_15f0e97.png) no-repeat;"></em></div>');
  488. var memoryTimeout = setTimeout(function () {
  489. skipPosition && jumpstart && jumpstart > player.video.currentTime && player.seek(jumpstart);
  490. $(".memory-play-wrap").remove();
  491. }, 15000);
  492. $(".memory-play-wrap .close-btn").click(function () {
  493. skipPosition && jumpstart && jumpstart > player.video.currentTime && player.seek(jumpstart);
  494. $(".memory-play-wrap").remove();
  495. clearTimeout(memoryTimeout);
  496. });
  497. $(".memory-play-wrap .play-jump").click(function () {
  498. player.seek(memoryTime - 1);
  499. $(".memory-play-wrap").remove();
  500. clearTimeout(memoryTimeout);
  501. });
  502. }
  503. }
  504. else {
  505. if (typeof skipPosition == "boolean") {
  506. skipPosition && jumpstart && player.seek(jumpstart);
  507. }
  508. }
  509. var duration = player.video.duration;
  510. document.onvisibilitychange = function () {
  511. if (document.visibilityState === "hidden") {
  512. var currentTime = player.video.currentTime;
  513. currentTime && obj.setPlayMemory(sign, currentTime, duration, jumpstart, jumpend);
  514. obj.setPlayMemory("last_file_id", sign);
  515. }
  516. };
  517. window.onbeforeunload = function () {
  518. var currentTime = player.video.currentTime;
  519. currentTime && obj.setPlayMemory(sign, currentTime, duration, jumpstart, jumpend);
  520. obj.setPlayMemory("last_file_id", sign);
  521. };
  522. $("[data-icon-type=PDSClose]").one("click", function () {
  523. var currentTime = player.video.currentTime;
  524. currentTime && obj.setPlayMemory(sign, currentTime, duration, jumpstart, jumpend);
  525. obj.setPlayMemory("last_file_id", sign);
  526. obj.autoLastBtn();
  527. });
  528. function formatVideoTime (seconds) {
  529. var secondTotal = Math.round(seconds)
  530. , hour = Math.floor(secondTotal / 3600)
  531. , minute = Math.floor((secondTotal - hour * 3600) / 60)
  532. , second = secondTotal - hour * 3600 - minute * 60;
  533. minute < 10 && (minute = "0" + minute);
  534. second < 10 && (second = "0" + second);
  535. return hour === 0 ? minute + ":" + second : hour + ":" + minute + ":" + second;
  536. }
  537. };
  538.  
  539. obj.autoSkipPlayNext = function () {
  540. var player = obj.video_page.player;
  541. player.on("timeupdate", function () {
  542. if (!this.autonext && obj.getPlayMemory("skipposition")) {
  543. var { video } = player;
  544. var { currentTime, duration } = video;
  545. var jumpStart = obj.getPlayMemory("jumpstart") || 60;
  546. var jumpEnd = obj.getPlayMemory("jumpend") || 120;
  547. if (!isNaN(duration) && jumpEnd > 0 && duration - currentTime <= parseInt(jumpEnd) + 10 * video.playbackRate) {
  548. this.autonext = true;
  549. var playInfo = obj.video_page.play_info;
  550. var fileList = obj.file_page.items
  551. , videoList = fileList.filter(function (item, index) {
  552. return item.category == "video";
  553. })
  554. , fileIndex, file = videoList.find(function (item, index) {
  555. fileIndex = index;
  556. return item.file_id == playInfo.file_id;
  557. })
  558. , sign = file ? file.file_id : "";
  559. obj.setPlayMemory(sign, currentTime + 10 * video.playbackRate, duration, jumpStart, jumpEnd);
  560. var fileNext = videoList[ fileIndex + 1 ];
  561. if (fileNext) {
  562. $(player.container).append('<div class="memory-play-wrap" style="display: block;position: absolute;left: 33px;bottom: 66px;font-size: 15px;padding: 7px;border-radius: 3px;color: #fff;z-index:100;background: rgba(0,0,0,.5);">10秒后自动下一集&nbsp;&nbsp;<a href="javascript:void(0);" class="play-jump" style="text-decoration: none;color: #06c;"> 取消 &nbsp;</a><em class="close-btn" style="display: inline-block;width: 15px;height: 15px;vertical-align: middle;cursor: pointer;background: url(https://nd-static.bdstatic.com/m-static/disk-share/widget/pageModule/share-file-main/fileType/video/img/video-flash-closebtn_15f0e97.png) no-repeat;"></em></div>');
  563. var memoryTimeout = setTimeout(function () {
  564. obj.playByFile(fileNext);
  565. $(".memory-play-wrap").remove();
  566. }, 10000);
  567. $(".memory-play-wrap .close-btn").click(function () {
  568. clearTimeout(memoryTimeout);
  569. $(".memory-play-wrap").remove();
  570. });
  571. $(".memory-play-wrap .play-jump").click(function () {
  572. clearTimeout(memoryTimeout);
  573. $(".memory-play-wrap").remove();
  574. });
  575. }
  576. else {
  577. obj.showTipError("没有下一集了");
  578. }
  579. }
  580. }
  581. });
  582. };
  583.  
  584. obj.playByFile = function(file) {
  585. var player = obj.video_page.player;
  586. if (player) {
  587. try {
  588. player.pause();
  589. player.docClickFun && document.removeEventListener('click', player.docClickFun, true);
  590. player.containerClickFun && player.container.removeEventListener('click', player.containerClickFun, true);
  591. player.fullScreen && player.fullScreen.destroy && player.fullScreen.destroy();
  592. player.hotkey && player.hotkey.destroy && player.hotkey.destroy();
  593. player.contextmenu && player.contextmenu.destroy && player.contextmenu.destroy();
  594. player.controller && player.controller.destroy && player.controller.destroy();
  595. player.timer && player.timer.destroy && player.timer.destroy();
  596. obj.video_page.player = null;
  597. obj.offsetCache = 0;
  598. } catch (error) { };
  599. }
  600. obj.video_page.play_info.file_id = file.file_id;
  601. obj.getVideoPreviewPlayInfo(function () {
  602. $(".header-file-name--CN_fq, .text--2KGvI").text(file.name);
  603. });
  604. };
  605.  
  606. obj.playByScroll = function() {
  607. // 继续上次播放 代码贡献:https://greasyfork.org/zh-CN/users/795227-星峰
  608. var last_file_id = obj.getPlayMemory("last_file_id");
  609. var fileList = obj.file_page.items
  610. , file = fileList.find(function (item, index) {
  611. return item.file_id == last_file_id;
  612. })
  613. , lastplay = file ? file.name : "";
  614. var soretype=$('.switch-wrapper--1yEfx .icon--d-ejA').attr("data-icon-type");
  615. var topp = 0;
  616. var scrollerdiv = $(".scroller--2hMGk,.grid-scroll--3o7hp");
  617. var he = 0;
  618. var url = location.href;
  619. if (url.indexOf(".aliyundrive.com/s/") > 0) {
  620. he = $(".thead--JwBMm,.top-element-wrapper--1iOwf").next().children().height();
  621. }
  622. else if (url.indexOf(".aliyundrive.com/drive") > 0) {
  623. he = scrollerdiv.children().children().height();
  624. }
  625. //通过文件列表定位上次播放文件
  626. var rownum=1;
  627. if(soretype=='PDSDrag'){//平铺模式
  628. var lastbox=$(".grid-card-container.first-row-item--AGVET:last");
  629. rownum=Number( lastbox.attr('data-index'))+1;
  630. }
  631. for(var i = 0; i < fileList.length; i++) {
  632. var tmptext = fileList[i].name;
  633. if (tmptext == lastplay) {
  634. topp = (parseInt(i/rownum) * (he / Math.ceil(fileList.length/rownum)));
  635. }
  636. }
  637. scrollerdiv.scrollTop(topp);
  638. setTimeout(() => {
  639. $(".text-primary--3DHOJ,.title--3x5k2").each( function () {
  640. var tmptext = this.textContent;
  641. if(tmptext == lastplay){
  642. this.click();
  643. }
  644. });
  645. },500)
  646. };
  647.  
  648. obj.autoLastBtn = function () {
  649. var lastplay = obj.getPlayMemory("last_file_id");
  650. lastplay ? $(".button-last--batch").show() : $(".button-last--batch").hide();
  651. };
  652.  
  653. obj.playSetting = function () {
  654. //将片头片尾放在设置里 代码贡献:https://greasyfork.org/zh-CN/users/795227-星峰
  655. if ($(".dplayer-setting-skipposition").length) return;
  656. var html = '<div class="dplayer-setting-item dplayer-setting-jumpend" style="display:none"><span class="dplayer-label" title="双击设置剩余时间为跳过片尾秒数">片尾(秒)</span><input type="text" name="dplayer-toggle" class="dplayer-toggle" style="height: 15px; font-size: 13px;border: 1px solid #fff;border-radius: 15px;"></div><div class="dplayer-setting-item dplayer-setting-jumpstart" style="display:none"><span class="dplayer-label" title="双击设置当前时间为跳过片头秒数">片头(秒)</span><input type="text" name="dplayer-toggle" class="dplayer-toggle" style="height: 15px; font-size: 13px;border: 1px solid #fff;border-radius: 15px;"></div><div class="dplayer-setting-item dplayer-setting-skipposition"><span class="dplayer-label">跳过片头片尾</span><div class="dplayer-toggle"><input class="dplayer-toggle-setting-input-skipposition" type="checkbox" name="dplayer-toggle"><label for="dplayer-toggle"></label></div></div>';
  657. html += '<div class="dplayer-setting-item dplayer-setting-autoposition"><span class="dplayer-label">自动记忆播放</span><div class="dplayer-toggle"><input class="dplayer-toggle-setting-input-autoposition" type="checkbox" name="dplayer-toggle"><label for="dplayer-toggle"></label></div></div>';
  658. $(".dplayer-setting-origin-panel").prepend(html);
  659. html = '<div class="dplayer-setting-item dplayer-setting-subtitle"><span class="dplayer-label">字幕设置</span></div></div>';
  660. $(".dplayer-setting-origin-panel").append(html);
  661. $(".dplayer-setting-subtitle").on("click", function() {
  662. obj.subtitleSetting();
  663. });
  664. $(".dplayer-mask").on("click",function() {
  665. if ($(".subtitle-setting-box").css("display") != "none") {
  666. $(".subtitle-setting-box").toggle();
  667. $(this).removeClass("dplayer-mask-show");
  668. }
  669. });
  670. var jumpstart = obj.getPlayMemory("jumpstart") || 60;
  671. var jumpend = obj.getPlayMemory("jumpend") || 120;
  672. var skipPosition = obj.getPlayMemory("skipposition");
  673. if (skipPosition) {
  674. $(".dplayer-toggle-setting-input-skipposition").get(0).checked = true;
  675. $(".dplayer-setting-jumpstart").show();
  676. $(".dplayer-setting-jumpend").show();
  677. }
  678. var txt = $(".dplayer-setting-jumpstart .dplayer-toggle");
  679. txt.val(jumpstart);
  680. txt.change(function() {
  681. obj.setPlayMemory("jumpstart", txt.val());
  682. jumpstart = txt.val();
  683. });
  684. txt.on('input propertychange', function(e) {
  685. var text = txt.val().replace(/[^\d]/g, "");
  686. txt.val(text);
  687. });
  688. var txt1 = $(".dplayer-setting-jumpend .dplayer-toggle");
  689. txt1.val(jumpend);
  690. txt1.change(function() {
  691. obj.setPlayMemory("jumpend", txt1.val());
  692. jumpend = txt1.val();
  693. });
  694. txt1.on('input propertychange', function(e) {
  695. var text = txt.val().replace(/[^\d]/g, "");
  696. txt.val(text);
  697. });
  698. $(".dplayer-setting-skipposition").on("click", function() {
  699. var check = $(".dplayer-toggle-setting-input-skipposition");
  700. var skipPosition = !check.is(":checked");
  701. $(".dplayer-toggle-setting-input-skipposition").get(0).checked = skipPosition;
  702. obj.setPlayMemory("skipposition", skipPosition);
  703. if (skipPosition) {
  704. $(".dplayer-setting-jumpstart").show()
  705. $(".dplayer-setting-jumpend").show()
  706. txt.val(jumpstart);
  707. txt1.val(jumpend);
  708. obj.setPlayMemory("jumpstart", jumpstart);
  709. obj.setPlayMemory("jumpend", jumpend);
  710. if($(".dplayer-setting-loop .dplayer-toggle-setting-input").is(":checked")) {
  711. $(".dplayer-setting-loop .dplayer-toggle-setting-input").click();
  712. }
  713. }
  714. else{
  715. $(".dplayer-setting-jumpstart").hide()
  716. $(".dplayer-setting-jumpend").hide()
  717. }
  718. });
  719. $(".dplayer-setting-jumpstart, .dplayer-setting-jumpend").on("dblclick", function() {
  720. let currtime = 0, video = obj.video_page.player.video, duration = parseInt(video.duration), currentTime = parseInt(video.currentTime);
  721. if($(this).hasClass("dplayer-setting-jumpstart")){
  722. currtime = currentTime;
  723. obj.setPlayMemory("jumpstart", currtime);
  724. }
  725. else{
  726. currtime = duration - currentTime;
  727. obj.setPlayMemory("jumpend", currtime);
  728. }
  729. $(this).children("input").val(currtime)
  730. });
  731. obj.getItem("dplayer-position") && ($(".dplayer-toggle-setting-input-autoposition").get(0).checked = true);
  732. $(".dplayer-setting-autoposition").on("click", function() {
  733. var check = $(".dplayer-toggle-setting-input-autoposition");
  734. var autoPosition = !check.is(":checked");
  735. $(".dplayer-toggle-setting-input-autoposition").get(0).checked = autoPosition;
  736. obj.setItem("dplayer-position", autoPosition);
  737. });
  738. $(".dplayer-setting-loop").on("click", function() {
  739. if ($(".dplayer-setting-loop .dplayer-toggle-setting-input").is(":checked") && skipPosition) {
  740. $(".dplayer-setting-skipposition").click();
  741. }
  742. $(".dplayer-setting-icon").click();
  743. });
  744. };
  745.  
  746. obj.selectEpisode = function () {
  747. //选集 代码贡献:https://greasyfork.org/zh-CN/users/795227-星峰
  748. if ($(".dplayer-icons-right #btn-select-episode").length) return;
  749. if (document.querySelectorAll(".dplayer-menu-item").length < 4) return;
  750. var fileList = obj.file_page.items
  751. , videoList = fileList.filter(function (item, index) {
  752. return item.category == "video";
  753. })
  754. , play_info = obj.video_page.play_info
  755. , fileIndex = videoList.findIndex(function (item, index) {
  756. return item.file_id == play_info.file_id;
  757. });
  758. if (!(fileIndex > -1 && videoList.length > 1)) return;
  759. var elevideo = "";
  760. videoList.forEach(function (item, index) {
  761. if (fileIndex == index) {
  762. elevideo += '<div class="video-item active" title="' + item.name + '" style="background-color: rgba(0,0,0,.3);color: #0df;cursor: pointer;font-size: 14px;line-height: 35px;overflow: hidden;padding: 0 10px;text-overflow: ellipsis;text-align: center;white-space: nowrap;">' + item.name + '</div>';
  763. }
  764. else {
  765. elevideo += '<div class="video-item" title="' + item.name + '" style="color: #fff;cursor: pointer;font-size: 14px;line-height: 35px;overflow: hidden;padding: 0 10px;text-overflow: ellipsis;text-align: center;white-space: nowrap;">' + item.name + '</div>';
  766. }
  767. });
  768. var svg = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 32 32"><path d="M22 16l-10.105-10.6-1.895 1.987 8.211 8.613-8.211 8.612 1.895 1.988 8.211-8.613z"></path></svg>'
  769. var html = '<button class="dplayer-icon dplayer-play-icon prev-icon" style="transform: rotate(-180deg)" title="上一集">'+ svg +'</button>';
  770. html += '<button id="btn-select-episode" class="dplayer-icon dplayer-quality-icon" title="选集">选集</button> <div class="playlist-content" style="max-width: 80%;max-height: 330px;width: auto;height: auto;box-sizing: border-box;overflow: hidden;position: absolute;left: 0;transition: all .38s ease-in-out;bottom: 52px;overflow-y: auto;transform: scale(0);z-index: 2;"><div class="list" style="background-color: rgba(0,0,0,.3);height: 100%;">' + elevideo + '</div></div>';
  771. html += '<button class="dplayer-icon dplayer-play-icon next-icon" title="下一集">'+ svg +'</button>';
  772. $(".dplayer-icons-right").prepend(html);
  773. $("#btn-select-episode").on("click", function() {
  774. var eleEpisode = $(".playlist-content");
  775. if (eleEpisode.css("transform").match(/\d+/) > 0) {
  776. eleEpisode.css("transform", "scale(0)");
  777. }
  778. else {
  779. eleEpisode.css("transform", "scale(1)");
  780. $(".dplayer-mask").addClass("dplayer-mask-show");
  781. var singleheight = $(".dplayer-icons-right .video-item")[0].offsetHeight;
  782. var totalheight = $(".dplayer-icons-right .playlist-content").height();
  783. $(".dplayer-icons-right .playlist-content").scrollTop((fileIndex + 1) * singleheight - totalheight / 2);
  784. }
  785. });
  786. $(".dplayer-mask").on("click",function() {
  787. var eleEpisode = $(".playlist-content");
  788. if (eleEpisode.css("transform").match(/\d+/) > 0) {
  789. eleEpisode.css("transform", "scale(0)");
  790. $(this).removeClass("dplayer-mask-show");
  791. }
  792. });
  793. $(".playlist-content .video-item").on("click", function() {
  794. var $this = $(this);
  795. if ($this.hasClass("active")) return;
  796. $(".dplayer-mask").removeClass("dplayer-mask-show");
  797. var oldele = $(".video-item.active");
  798. oldele.removeClass("active");
  799. oldele.css({"background-color": "", "color": "#fff"});
  800. $this.addClass("active");
  801. $this.css({"background-color": "rgba(0,0,0,.3)", "color": "#0df"});
  802. var file = videoList[$this.index()];
  803. obj.playByFile(file);
  804. });
  805. $(".prev-icon").on("click", function () {
  806. var file = videoList[fileIndex - 1];
  807. file ? obj.playByFile(file) : obj.showTipError("没有上一集了");
  808. });
  809. $(".next-icon").on("click",function(){
  810. var file = videoList[fileIndex + 1];
  811. file ? obj.playByFile(file) : obj.showTipError("没有下一集了");
  812. });
  813. };
  814.  
  815. obj.selectSubtitles = function (textTracks) {
  816. if (textTracks.length <= 1) return;
  817. if ($(".dplayer-subtitle-btn .dplayer-quality-mask").length) {
  818. $(".dplayer-subtitle-btn .dplayer-quality-mask").remove();
  819. }
  820. var subbtn = $(".dplayer-subtitle-btn")
  821. subbtn.addClass("dplayer-quality");
  822. var fileId = obj.video_page.play_info.file_id
  823. , sub_info = obj.video_page.sub_info;
  824. var subList = sub_info[fileId];
  825. var eleSub = '<div class="dplayer-quality-item subtitle-item" data-index="'+ 0 +'" style="opacity: 0.4;">默认字幕</div>';
  826. for(var i = 1; i < subList.length; i++) {
  827. eleSub += '<div class="dplayer-quality-item subtitle-item" data-index="'+ i +'">'+ subList[i].label +'</div>';
  828. }
  829. var html = '<div class="dplayer-quality-mask"><div class="dplayer-quality-list subtitle-select"> '+ eleSub +'</div></div>'
  830. subbtn.append(html);
  831. $(".subtitle-select .subtitle-item").off("click").on("click", function() {
  832. var $this = $(this), index = $this.attr("data-index");
  833. if ($this.css("opacity") != .4) {
  834. $this.css("opacity", .4);
  835. $this.siblings().css("opacity", "");
  836. var subPicBtn = $(".dplayer-subtitle-btn .dplayer-icon");
  837. subPicBtn.attr("data-balloon") == "显示字幕" && subPicBtn.click();
  838. var subitem = subList[index];
  839. if (subitem && subitem.sarr && subitem.sarr.length) {
  840. for(var i = textTracks[0].cues.length - 1; i >= 0; i--) {
  841. textTracks[0].removeCue(textTracks[0].cues[i]);
  842. }
  843. subitem.sarr.forEach(function (item) {
  844. /<b>.*<\/b>/.test(item.text) || (item.text = item.text.split(/\r?\n/).map((item) => `<b>${item}</b>`).join("\n"));
  845. var textTrackCue = new VTTCue(item.startTime, item.endTime, item.text);
  846. textTrackCue.id = item.index;
  847. textTracks[0] && textTracks[0].addCue(textTrackCue);
  848. });
  849. sub_info.index = index;
  850. }
  851. }
  852. });
  853. var index = sub_info.index;
  854. index && $(".subtitle-select .subtitle-item").eq(index).click();
  855. };
  856.  
  857. obj.dPlayerSubtitleStyle = function () {
  858. const player = obj.video_page.player;
  859. const { subtitle: { container: { style } } } = player;
  860. const bottom = localStorage.getItem("dplayer-subtitle-bottom")
  861. , color = localStorage.getItem("dplayer-subtitle-color")
  862. , fontSize = localStorage.getItem("dplayer-subtitle-fontSize");
  863. style.fontSize == fontSize + "vh" || (style.fontSize = fontSize + "vh");
  864. style.bottom == bottom + "%" || (style.bottom = bottom + "%");
  865. style.color == color || (style.color = color);
  866. style.textShadow || (style.textShadow = "1px 0 1px #000, 0 1px 1px #000, -1px 0 1px #000, 0 -1px 1px #000, 1px 1px 1px #000, -1px -1px 1px #000, 1px -1px 1px #000, -1px 1px 1px #000");
  867. if (!style.fontFamily) {
  868. const fontFamilys = ["黑体", "楷体", "宋体", "微软雅黑", "Trajan", "serif"]
  869. , rand_font = Math.floor(Math.random() * fontFamilys.length);
  870. style.fontFamily = fontFamilys[rand_font];
  871. }
  872. };
  873.  
  874. obj.subtitleSetting = function () {
  875. var subSetBox = $(".subtitle-setting-box");
  876. if (subSetBox.length) {
  877. return subSetBox.toggle();
  878. }
  879. else {
  880. var html = '<div class="dplayer-icons dplayer-comment-box subtitle-setting-box" style="display: block; z-index: 111; position: absolute; bottom: 10px;left:auto; right: 400px !important;"><div class="dplayer-comment-setting-box dplayer-comment-setting-open" >';
  881. html += '<div class="dplayer-comment-setting-color"><div class="dplayer-comment-setting-title">字幕颜色<input type="text" class="color-value" style="height: 16px;width: 70px;font-size: 14px;border: 1px solid #fff;border-radius: 3px;margin-left: 70px;color: black;text-align: center;"></div><label><input type="radio" name="dplayer-danmaku-color-1" value="#fff" checked=""><span style="background: #fff;"></span></label><label><input type="radio" name="dplayer-danmaku-color-1" value="#e54256"><span style="background: #e54256"></span></label><label><input type="radio" name="dplayer-danmaku-color-1" value="#ffe133"><span style="background: #ffe133"></span></label><label><input type="radio" name="dplayer-danmaku-color-1" value="#64DD17"><span style="background: #64DD17"></span></label><label><input type="radio" name="dplayer-danmaku-color-1" value="#39ccff"><span style="background: #39ccff"></span></label><label><input type="radio" name="dplayer-danmaku-color-1" value="#D500F9"><span style="background: #D500F9"></span></label></div>';
  882. html += '<div class="dplayer-comment-setting-type"><div class="dplayer-comment-setting-title">字幕位置</div><label><input type="radio" name="dplayer-danmaku-type-1" value="1"><span>上移</span></label><label><input type="radio" name="dplayer-danmaku-type-1" value="0" checked=""><span>默认</span></label><label><input type="radio" name="dplayer-danmaku-type-1" value="2"><span>下移</span></label></div>';
  883. html += '<div class="dplayer-comment-setting-type"><div class="dplayer-comment-setting-title">字幕大小</div><label><input type="radio" name="dplayer-danmaku-type-1" value="1"><span>加大</span></label><label><input type="radio" name="dplayer-danmaku-type-1" value="0"><span>默认</span></label><label><input type="radio" name="dplayer-danmaku-type-1" value="2"><span>减小</span></label></div>';
  884. html += '<div class="dplayer-comment-setting-type"><div class="dplayer-comment-setting-title">字幕偏移<span class="offset-text" style="border: 0px;width: 58px;"></span>偏移量 <input type="number" class="offset-value" style="height: 14px;width: 42px;font-size: 13px;border: 1px solid #fff;border-radius: 3px;color: black;line-height: normal;text-align: center;" step="1" min="1"></div><label><input type="radio" name="dplayer-danmaku-type-1" value="1"><span>前移</span></label><label><input type="radio" name="dplayer-danmaku-type-1" value="0"><span>默认</span></label><label><input type="radio" name="dplayer-danmaku-type-1" value="2"><span>后移</span></label></div>';
  885. html += '<div class="dplayer-comment-setting-type"><div class="dplayer-comment-setting-title">更多字幕功能</div><label><input type="radio" name="dplayer-danmaku-type-1" value="1"><span>本地字幕</span></label><label><input type="radio" name="dplayer-danmaku-type-1" value="0"><span>待定</span></label><label><input type="radio" name="dplayer-danmaku-type-1" value="2"><span>网络字幕</span></label></div>';
  886. html += '</div></div>';
  887. $(".dplayer-controller").append(html);
  888. subSetBox = $(".subtitle-setting-box");
  889. var colortxt = $(".color-value");
  890. colortxt.val(localStorage.getItem("dplayer-subtitle-color")||"#ffe133")
  891. colortxt.on('input propertychange', function(e) {
  892. var color = colortxt.val();
  893. color = color.replace(/[^#0-9a-fA-F]/g, "");//排除#和十六进制字符
  894. color = color.replace(/^[0-9a-fA-F]/g, "");//排除非#开头
  895. color = color.replace("#", "$@$").replace(/\#/g, "").replace("$@$", "#");//排除多个#
  896. color = color.replace(/^#([0-9a-fA-F]{3,6}).*$/, '#$1');//排除十六进制字符长度超过6位
  897.  
  898. colortxt.val(color);
  899. if (localStorage.getItem("dplayer-subtitle-color") != color) {
  900. localStorage.setItem("dplayer-subtitle-color", color);
  901. $(".dplayer-subtitle").css("color", color);
  902. }
  903. });
  904. var txt = $(".offset-value");
  905. txt.val("5");
  906. txt.on('input propertychange', function(e) {
  907. var text = txt.val().replace(/[^\d]/g, "");
  908. txt.val(text);
  909. });
  910. }
  911. $(".subtitle-setting-box .dplayer-comment-setting-color input[type='radio']").on("click",function() {
  912. var color = this.value;
  913. if (localStorage.getItem("dplayer-subtitle-color") != color) {
  914. localStorage.setItem("dplayer-subtitle-color", color);
  915. $(".dplayer-subtitle").css("color", color);
  916. }
  917. colortxt.val(color)
  918. });
  919. $(".subtitle-setting-box .dplayer-comment-setting-type input[type='radio']").on("click",function() {
  920. var value = this.value;
  921. var $this = $(this), $name = $this.parent().parent().children(":first").text();
  922. if ($name == "字幕位置") {
  923. var bottom = Number(localStorage.getItem("dplayer-subtitle-bottom") || 10);
  924. value == "1" ? bottom += 1 : value == "2" ? bottom -= 1 : bottom = 10;
  925. localStorage.setItem("dplayer-subtitle-bottom", bottom);
  926. $(".dplayer-subtitle").css("bottom", bottom + "%");
  927. }
  928. else if ($name == "字幕大小") {
  929. var fontSize = Number(localStorage.getItem("dplayer-subtitle-fontSize") || 5);
  930. value == "1" ? fontSize += .1 : value == "2" ? fontSize -= .1 : fontSize = 5;
  931. localStorage.setItem("dplayer-subtitle-fontSize", fontSize);
  932. $(".dplayer-subtitle").css("font-size", fontSize + "vh");
  933. }
  934. else if ($name.includes("字幕偏移")){
  935. var offsettime = obj.offsetCache || 0;
  936. var offsetvalue = Number($(".offset-value").val()) || 5;
  937. value == "1" ? offsettime -= offsetvalue : value == "2" ? offsettime += offsetvalue : offsettime = 0;
  938. offsettime == 0 ? $(".offset-text").text("") : $(".offset-text").text("["+ offsettime +"s]");
  939. obj.offsetCache = offsettime;
  940. obj.subtitleOffset();
  941. }
  942. else if ($name == "更多字幕功能") {
  943. if (value == "0") {
  944. $this.next().text("暂无");
  945. setTimeout (function () {
  946. $this.next().text("待定")
  947. }, 5000);
  948. }
  949. else if (value == "1") {
  950. if ($("#addsubtitle").length == 0) {
  951. $("body").append('<input id="addsubtitle" type="file" accept=".srt,.ass,.ssa,.vtt" style="display: none;">');
  952. }
  953. $("#addsubtitle").click();
  954. $this.next().text("请等待...");
  955. setTimeout (function () {
  956. $this.next().text("本地字幕")
  957. }, 5000);
  958. }
  959. else if (value == "2") {
  960. $this.next().text("暂无");
  961. setTimeout (function () {
  962. $this.next().text("网络字幕")
  963. }, 5000);
  964. }
  965. }
  966. });
  967. };
  968.  
  969. obj.subtitleOffset = function () {
  970. const player = obj.video_page.player;
  971. const { video, subtitle } = player;
  972. if (video.textTracks && video.textTracks[0]) {
  973. const track = video.textTracks[0];
  974. const cues = Array.from(track.cues);
  975. let fileId = obj.video_page.play_info.file_id
  976. , sub_info = obj.video_page.sub_info
  977. , subList = sub_info[fileId]
  978. , index = sub_info.index || 0
  979. , sarr = subList[index].sarr;
  980. let offsetCache = obj.offsetCache || 0;
  981. for (let index = 0; index < cues.length; index++) {
  982. const cue = cues[index];
  983. cue.startTime = clamp(sarr[index].startTime + offsetCache, 0, video.duration);
  984. cue.endTime = clamp(sarr[index].endTime + offsetCache, 0, video.duration);
  985. }
  986. subtitle.init();
  987. player.notice(`字幕偏移: ${offsetCache} 秒`);
  988. }
  989. else {
  990. obj.offsetCache = 0;
  991. }
  992. function clamp(num, a, b) {
  993. return Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b));
  994. }
  995. };
  996.  
  997. obj.getPlayMemory = function (e) {
  998. var fileList = obj.file_page.items
  999. , parent_file_id = fileList[0].parent_file_id
  1000. , videoMemory = obj.getItem("video_memory");
  1001. if (videoMemory && videoMemory[parent_file_id]) {
  1002. return videoMemory[parent_file_id][e];
  1003. }
  1004. return "";
  1005. };
  1006.  
  1007. obj.setPlayMemory = function (e, t, o, start, end) {
  1008. if (e) {
  1009. var fileList = obj.file_page.items
  1010. , parent_file_id = fileList[0].parent_file_id
  1011. , videoMemory = obj.getItem("video_memory") || {};
  1012. if (typeof t == "number" && o) {
  1013. if ((start && (t <= parseInt(start)) || end && (t + parseInt(end) >= o))) {
  1014. if (videoMemory.hasOwnProperty(parent_file_id) && videoMemory[parent_file_id].hasOwnProperty(e)) {
  1015. delete videoMemory[parent_file_id][e];
  1016. }
  1017. }
  1018. else {
  1019. videoMemory[parent_file_id] || (videoMemory[parent_file_id] = {});
  1020. videoMemory[parent_file_id][e] = t;
  1021. }
  1022. obj.setItem("video_memory", videoMemory);
  1023. }
  1024. else {
  1025. Object.keys(videoMemory).forEach(function (key) {
  1026. var time = videoMemory[key].time;
  1027. if (time && (parseInt(Date.now() / 1000) - time >= 864000)) {
  1028. delete videoMemory[key];
  1029. }
  1030. });
  1031. if (!videoMemory[parent_file_id]) {
  1032. videoMemory[parent_file_id] = {
  1033. time: parseInt(Date.now() / 1000)
  1034. };
  1035. }
  1036. videoMemory[parent_file_id][e] = t;
  1037. obj.setItem("video_memory", videoMemory);
  1038. }
  1039. }
  1040. };
  1041.  
  1042. obj.getVideoPreviewPlayInfo = function (callback) {
  1043. obj.refresh_token(function (result) {
  1044. if (result) {
  1045. if (obj.isHomePage()) {
  1046. obj.get_video_preview_play_info(callback);
  1047. }
  1048. else {
  1049. obj.get_share_token(function (result) {
  1050. if (result) {
  1051. obj.get_share_link_video_preview_play_info(callback);
  1052. }
  1053. else {
  1054. callback && callback("");
  1055. }
  1056. });
  1057. }
  1058. }
  1059. else {
  1060. callback && callback("");
  1061. }
  1062. });
  1063. };
  1064.  
  1065. obj.get_share_link_video_preview_play_info = function (callback) {
  1066. var token = obj.getItem("token") || {}, share_id = obj.getShareId(), file_id = obj.video_page.play_info.file_id;
  1067. $.ajax({
  1068. type: "post",
  1069. url: "https://api.aliyundrive.com/v2/file/get_share_link_video_preview_play_info",
  1070. data: JSON.stringify({
  1071. category: "live_transcoding",
  1072. file_id: file_id,
  1073. get_preview_url: true,
  1074. share_id: share_id,
  1075. template_id: "",
  1076. get_subtitle_info: !0
  1077. }),
  1078. headers: {
  1079. "authorization": "".concat(token.token_type || "", " ").concat(token.access_token || ""),
  1080. "content-type": "application/json;charset=UTF-8",
  1081. "x-share-token": obj.getItem("shareToken").share_token
  1082. },
  1083. async: true,
  1084. success: function (response) {
  1085. callback && callback(response);
  1086. },
  1087. error: function (error) {
  1088. console.error("get_share_link_video_preview_play_info error", error);
  1089. callback && callback("");
  1090. }
  1091. });
  1092. };
  1093.  
  1094. obj.get_video_preview_play_info = function (callback) {
  1095. var token = obj.getItem("token") || {}, file_id = obj.video_page.play_info.file_id;
  1096. $.ajax({
  1097. type: "post",
  1098. url: "https://api.aliyundrive.com/v2/file/get_video_preview_play_info",
  1099. data: JSON.stringify({
  1100. category: "live_transcoding",
  1101. drive_id: token.default_drive_id,
  1102. file_id: file_id,
  1103. template_id: "",
  1104. get_subtitle_info: !0
  1105. }),
  1106. headers: {
  1107. "authorization": "".concat(token.token_type || "", " ").concat(token.access_token || ""),
  1108. "content-type": "application/json;charset=UTF-8",
  1109. },
  1110. async: true,
  1111. success: function (response) {
  1112. callback && callback(response);
  1113. },
  1114. error: function (error) {
  1115. console.error("get_video_preview_play_info error", error);
  1116. callback && callback("");
  1117. }
  1118. });
  1119. };
  1120.  
  1121. obj.isUrlExpires = function (e) {
  1122. var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : 6e3
  1123. , n = obj.dPlayerSupport.toString().length == 1946 && e.match(/&x-oss-expires=(\d+)&/);
  1124. return !n || n && n[1] && +"".concat(n[1], "000") - t < Date.now();
  1125. };
  1126.  
  1127. obj.addCueVideoSubtitle = function (callback) {
  1128. obj.getSubList(function (sublist) {
  1129. if (sublist && sublist.length && sublist[0]) {
  1130. const { video } = obj.video_page.player;
  1131. var textTracks = video.textTracks;
  1132. for (let i = 0; i < textTracks.length; i++) {
  1133. textTracks[i].mode = "hidden" || (textTracks[i].mode = "hidden");
  1134. if (textTracks[i].cues && textTracks[i].cues.length) {
  1135. for(let ii = textTracks[i].cues.length - 1; ii >= 0; ii--) {
  1136. textTracks[i].removeCue(textTracks[i].cues[ii]);
  1137. }
  1138. }
  1139. }
  1140. sublist.forEach(function (item, index) {
  1141. if (item.sarr) {
  1142. textTracks[index] || video.addTextTrack("subtitles", item.label, item.language);
  1143. item.sarr.forEach(function (item) {
  1144. /<b>.*<\/b>/.test(item.text) || (item.text = item.text.split(/\r?\n/).map((item) => `<b>${item}</b>`).join("\n"));
  1145. var textTrackCue = new VTTCue(item.startTime, item.endTime, item.text);
  1146. textTrackCue.id = item.index;
  1147. textTracks[index] && textTracks[index].addCue(textTrackCue);
  1148. });
  1149. }
  1150. });
  1151. var textTrack = textTracks[0];
  1152. if (textTrack && textTrack.cues && textTrack.cues.length && obj.isAppreciation.toString().length == 1367) {
  1153. textTrack.mode = "showing";
  1154. obj.showTipSuccess("字幕添加成功");
  1155. callback && callback(textTracks);
  1156. }
  1157. }
  1158. });
  1159. };
  1160.  
  1161. obj.getSubList = function (callback) {
  1162. var fileId = obj.video_page.play_info.file_id
  1163. , sub_info = obj.video_page.sub_info;
  1164. if (sub_info.hasOwnProperty(fileId)) {
  1165. return callback && callback(sub_info[fileId]);
  1166. }
  1167. sub_info.index = 0;
  1168. var currSubList = sub_info[fileId] = [];
  1169. obj.subtitleTaskList(function (sublist) {
  1170. if (Array.isArray(sublist) && sublist[0]) {
  1171. currSubList = currSubList.concat(sublist);
  1172. currSubList = obj.sortSubList(currSubList);
  1173. sub_info[fileId] = currSubList;
  1174. callback && callback(currSubList);
  1175. }
  1176. });
  1177. obj.subtitleFolderList(function (sublist) {
  1178. if (Array.isArray(sublist) && sublist[0]) {
  1179. currSubList = currSubList.concat(sublist);
  1180. currSubList = obj.sortSubList(currSubList);
  1181. sub_info[fileId] = currSubList;
  1182. callback && callback(currSubList);
  1183. }
  1184. });
  1185. obj.subtitleLocalFile(function (sublist) {
  1186. if (Array.isArray(sublist) && sublist[0]) {
  1187. currSubList = currSubList.concat(sublist);
  1188. currSubList = obj.sortSubList(currSubList);
  1189. sub_info[fileId] = currSubList;
  1190. callback && callback(currSubList);
  1191. }
  1192. });
  1193. };
  1194.  
  1195. obj.subtitleTaskList = function (callback) {
  1196. var sublist = obj.video_page.play_info.video_preview_play_info.live_transcoding_subtitle_task_list;
  1197. if (sublist && sublist.length) {
  1198. var sublistLen = sublist.length;
  1199. sublist.forEach(function (item, index) {
  1200. item.language || (item.language = "chi");
  1201. item.label || (item.label = obj.langCodeTransform(item.language));
  1202. obj.surlRequest(item.url, function (text) {
  1203. var sarr = obj.subtitleParser(text, "vtt");
  1204. if (Array.isArray(sarr) && sarr.length) {
  1205. sarr = obj.fuseSubArr(sarr);
  1206. item.sarr = sarr;
  1207. }
  1208. if (--sublistLen == 0) {
  1209. callback && callback(sublist.filter(function (item, index) {
  1210. return item.sarr;
  1211. }));
  1212. }
  1213. });
  1214. });
  1215. }
  1216. else {
  1217. callback && callback("");
  1218. }
  1219. };
  1220.  
  1221. obj.subtitleFolderList = function (callback) {
  1222. var subFileList = obj.searchFolderSubList();
  1223. if (subFileList && subFileList.length) {
  1224. obj.subFileListDownloadUrl(subFileList, function(fileList) {
  1225. var subFileListLen = subFileList.length;
  1226. fileList.forEach(function (item, index) {
  1227. item.language || (item.language = "chi");
  1228. item.label || (item.label = obj.langCodeTransform(item.language));
  1229. item.sext = item.file_extension.toLowerCase();
  1230. obj.surlRequest(item.download_url || item.url, function (stext) {
  1231. var sarr = obj.subtitleParser(stext, item.sext);
  1232. if (Array.isArray(sarr)) {
  1233. sarr = obj.fuseSubArr(sarr);
  1234. item.sarr = sarr;
  1235. }
  1236. if (--subFileListLen == 0) {
  1237. callback && callback(subFileList.filter(function (item, index) {
  1238. return item.sarr;
  1239. }));
  1240. }
  1241. });
  1242. });
  1243. });
  1244. }
  1245. else {
  1246. callback && callback("");
  1247. }
  1248. };
  1249.  
  1250. obj.searchFolderSubList = function () {
  1251. var fileList = obj.file_page.items
  1252. , playInfo = obj.video_page.play_info
  1253. , subExts = ["webvtt", "vtt", "srt", "ssa", "ass"]
  1254. , vname = "";
  1255. var videoList = [], subList = fileList.filter(function (item) {
  1256. if (item.type == "file") {
  1257. if (item.file_id == playInfo.file_id) {
  1258. vname = item.name.replace("." + item.file_extension, "").toLowerCase();
  1259. }
  1260. if (item.category == "video") {
  1261. videoList.push(item);
  1262. }
  1263. return subExts.includes(item.file_extension.toLowerCase());
  1264. }
  1265. else {
  1266. return false;
  1267. }
  1268. });
  1269. if (subList.length) {
  1270. if (videoList.length == 1) {
  1271. return subList;
  1272. }
  1273. else {
  1274. var getSubList = function () {
  1275. var _subList = subList.filter(function (item) {
  1276. var fileName = item.name.replace("." + item.file_extension, "").toLowerCase();
  1277. return fileName.includes(vname) || vname.includes(fileName);
  1278. });
  1279. if (_subList.length) {
  1280. return _subList ;
  1281. }
  1282. else {
  1283. vname = vname.split(".").slice(0, -1).join(".");
  1284. if (vname) {
  1285. return getSubList();
  1286. }
  1287. else {
  1288. return "";
  1289. }
  1290. }
  1291. };
  1292. return getSubList();
  1293. }
  1294. }
  1295. else {
  1296. return "";
  1297. }
  1298. };
  1299.  
  1300. obj.subFileListDownloadUrl = function (fileList, callback) {
  1301. var shareId = obj.getShareId();
  1302. if (shareId) {
  1303. obj.getShareLinkDownloadUrlAll(fileList, callback);
  1304. }
  1305. else {
  1306. obj.getHomeLinkDownloadUrlAll(fileList, callback);
  1307. }
  1308. };
  1309.  
  1310. obj.subtitleLocalFile = function (callback) {
  1311. obj.localFileForText(function (fileInfo) {
  1312. if (fileInfo.stext) {
  1313. fileInfo.sarr = obj.subtitleParser(fileInfo.stext, fileInfo.sext);
  1314. if (fileInfo.sarr.length) {
  1315. fileInfo.language = obj.langDetectSarr(fileInfo.sarr);
  1316. fileInfo.label = obj.langCodeTransform(fileInfo.language);
  1317. callback && callback([ fileInfo ]);
  1318. }
  1319. else {
  1320. callback && callback("");
  1321. }
  1322. }
  1323. else {
  1324. obj.showTipError("本地字幕添加失败");
  1325. callback && callback("");
  1326. }
  1327. });
  1328. };
  1329.  
  1330. obj.localFileForText = function (callback) {
  1331. $(document).on("change", "#addsubtitle", function(event) {
  1332. if (this.files.length) {
  1333. var file = this.files[0];
  1334. var file_ext = file.name.split(".").pop().toLowerCase();
  1335. var sexts = ["webvtt", "vtt", "srt", "ssa", "ass"];
  1336. if (!(file_ext && sexts.includes(file_ext))) {
  1337. obj.showTipError("暂不支持此类型文件");
  1338. return callback && callback("");
  1339. }
  1340. var reader = new FileReader();
  1341. reader.readAsText(file, 'UTF-8');
  1342. reader.onload = function(event) {
  1343. var result = reader.result;
  1344. if (result.indexOf("�") > -1) {
  1345. return reader.readAsText(file, "GBK");
  1346. }
  1347. else if (result.indexOf("") > -1) {
  1348. return reader.readAsText(file, "BIG5");
  1349. }
  1350. callback && callback({sext: file_ext, stext: result});
  1351. };
  1352. reader.onerror = function(e) {
  1353. callback && callback("");
  1354. };
  1355. }
  1356. this.value = "";
  1357. event.target.value = "";
  1358. });
  1359. $(document).on("change", ".afdian-order", function () {
  1360. if (this.value) {
  1361. if (this.value.match(/^202[\d]{22,25}$/)) {
  1362. if (this.value.match(/(\d)\1{7,}/g)) return;
  1363. localforage.getItem("users", (error, data) => {
  1364. (data && data.ON == this.value) || obj.onPost(this.value);
  1365. });
  1366. }
  1367. else {
  1368. obj.showTipError("\u6b64\u8ba2\u5355\u53f7\u4e0d\u5408\u89c4\u8303\uff0c\u8bf7\u91cd\u8bd5");
  1369. }
  1370. }
  1371. });
  1372. };
  1373.  
  1374. obj.surlRequest = function (url, callback) {
  1375. fetch(url, {
  1376. referrer: "https://www.aliyundrive.com/",
  1377. referrerPolicy: "origin",
  1378. body: null,
  1379. method: "GET",
  1380. mode: "cors",
  1381. credentials: "omit"
  1382. }).then(data => data.blob()).then(blob => {
  1383. var reader = new FileReader();
  1384. reader.readAsText(blob, "UTF-8");
  1385. reader.onload = function(e) {
  1386. var result = reader.result;
  1387. if (result.indexOf("�") > -1 && !reader.markGBK) {
  1388. reader.markGBK = true;
  1389. return reader.readAsText(blob, "GBK");
  1390. }
  1391. else if (result.indexOf("") > -1 && !reader.markBIG5) {
  1392. reader.markBIG5 = true;
  1393. return reader.readAsText(blob, "BIG5");
  1394. }
  1395. callback && callback(result);
  1396. };
  1397. reader.onerror = function(e) {
  1398. callback && callback("");
  1399. };
  1400. }).catch(function(error) {
  1401. callback && callback("");
  1402. });
  1403. };
  1404.  
  1405. obj.subtitleParser = function(stext, sext) {
  1406. sext || (stext.indexOf("->") > 0 ? "srt" : stext.indexOf("Dialogue:") > 0 ? "ass" : "");
  1407. sext = sext.toLowerCase();
  1408. var regex, data, items = [];
  1409. switch(sext) {
  1410. case "webvtt":
  1411. case "vtt":
  1412. case "srt":
  1413. stext = stext.replace(/\r/g, "");
  1414. regex = /(\d+)?\n?(\d{0,2}:?\d{2}:\d{2}.\d{3}) -?-> (\d{0,2}:?\d{2}:\d{2}.\d{3})/g;
  1415. data = stext.split(regex);
  1416. data.shift();
  1417. for (let i = 0; i < data.length; i += 4) {
  1418. items.push({
  1419. index: items.length,
  1420. startTime: obj.parseTimestamp(data[i + 1]),
  1421. endTime: obj.parseTimestamp(data[i + 2]),
  1422. text: data[i + 3].trim().replace(/{.*?}/g, "").replace(/[a-z]+\:.*\d+\.\d+\%\s/, "")
  1423. });
  1424. }
  1425. return items;
  1426. case "ssa":
  1427. case "ass":
  1428. stext = stext.replace(/\r\n/g, "");
  1429. regex = /Dialogue: .*?\d+,(\d+:\d{2}:\d{2}\.\d{2}),(\d+:\d{2}:\d{2}\.\d{2}),.*?,\d+,\d+,\d+,.*?,/g;
  1430. data = stext.split(regex);
  1431. data.shift();
  1432. for (let i = 0; i < data.length; i += 3) {
  1433. items.push({
  1434. index: items.length,
  1435. startTime: obj.parseTimestamp(data[i]),
  1436. endTime: obj.parseTimestamp(data[i + 1]),
  1437. text: data[i + 2].trim().replace(/\\N/g, "\n").replace(/{.*?}/g, "")
  1438. });
  1439. }
  1440. return items;
  1441. default:
  1442. console.error("未知字幕格式,无法解析", stext, sext);
  1443. return items;
  1444. }
  1445. };
  1446.  
  1447. obj.parseTimestamp = function(e) {
  1448. var t = e.split(":")
  1449. , n = parseFloat(t.length > 0 ? t.pop().replace(/,/g, ".") : "00.000") || 0
  1450. , r = parseFloat(t.length > 0 ? t.pop() : "00") || 0;
  1451. return 3600 * (parseFloat(t.length > 0 ? t.pop() : "00") || 0) + 60 * r + n;
  1452. };
  1453.  
  1454. obj.langDetectSarr = function (sarr) {
  1455. var t = [
  1456. sarr[parseInt(sarr.length / 3)].text,
  1457. sarr[parseInt(sarr.length / 2)].text,
  1458. sarr[parseInt(sarr.length / 3 * 2)].text
  1459. ].join("").replace(/[<bi\/>\r?\n]*/g, "");
  1460. var e = "eng"
  1461. , i = (t.match(/[\u4e00-\u9fa5]/g) || []).length / t.length;
  1462. (t.match(/[\u3020-\u303F]|[\u3040-\u309F]|[\u30A0-\u30FF]|[\u31F0-\u31FF]/g) || []).length / t.length > .03 ? e = "jpn" : i > .1 && (e = "zho");
  1463. return e;
  1464. };
  1465.  
  1466. obj.langCodeTransform = function (language) {
  1467. return {
  1468. chi: "中文字幕",
  1469. zho: "中文字幕",
  1470. eng: "英文字幕",
  1471. jpn: "日文字幕"
  1472. }[language] || "未知语言";
  1473. };
  1474.  
  1475. obj.sortSubList = function (sublist) {
  1476. var chlist = [], otherlist = [];
  1477. sublist.forEach(function (item, index) {
  1478. ["chi", "zho"].includes(item.language) ? chlist.push(item) : otherlist.push(item);
  1479. });
  1480. return chlist.concat(otherlist);
  1481. };
  1482.  
  1483. obj.fuseSubArr = function (sarr) {
  1484. var newsarr = [ sarr.shift() ];
  1485. sarr.forEach(function (item, index) {
  1486. var prevsub = newsarr.slice(-1);
  1487. if (item.startTime == prevsub.startTime && item.endTime == prevsub.endTime) {
  1488. prevsub.text += "\n" + item.text;
  1489. }
  1490. else {
  1491. newsarr.push(item);
  1492. }
  1493. });
  1494. return newsarr;
  1495. };
  1496.  
  1497. obj.loadScript = function (src) {
  1498. if (!window.instances) {
  1499. window.instances = {};
  1500. }
  1501. if (!window.instances[src]) {
  1502. window.instances[src] = new Promise((resolve, reject) => {
  1503. const script = document.createElement("script")
  1504. script.src = src;
  1505. script.type = "text/javascript";
  1506. script.onload = resolve;
  1507. script.onerror = reject;
  1508. document.head.appendChild(script);
  1509. });
  1510. }
  1511. return window.instances[src];
  1512. };
  1513.  
  1514. obj.initDownloadSharePage = function () {
  1515. if ($(".button-download--batch").length) {
  1516. return;
  1517. }
  1518. if ($("#root [class^=banner] [class^=right]").length) {
  1519. var html = '';
  1520. html += '<button class="button--2Aa4u primary--3AJe5 small---B8mi button-last--batch" style="margin-right: 28px;">继续上次播放</button>';
  1521. html += '<button class="button--2Aa4u primary--3AJe5 small---B8mi button-download--batch" style="margin-right: 28px;">显示链接</button>';
  1522. $("#root [class^=banner] [class^=right]").prepend(html);
  1523. $(".button-download--batch").on("click", obj.showDownloadSharePage);
  1524. $(".button-last--batch").on("click", function () {
  1525. obj.playByScroll();
  1526. });
  1527. }
  1528. else {
  1529. setTimeout(obj.initDownloadSharePage, 500)
  1530. }
  1531. };
  1532.  
  1533. obj.initDownloadHomePage = function () {
  1534. if ($(".button-download--batch").length) {
  1535. return;
  1536. }
  1537. if ($("#root header").length) {
  1538. var html = '';
  1539. html += '<div style="margin:0px 8px;"></div><button class="button--2Aa4u primary--3AJe5 small---B8mi button-last--batch">继续上次播放</button>';
  1540. html += '<div style="margin:0px 8px;"></div><button class="button--2Aa4u primary--3AJe5 small---B8mi button-download--batch">显示链接</button>';
  1541. $("#root header:eq(0)").append(html);
  1542. $(".button-download--batch").on("click", obj.showDownloadHomePage);
  1543. $(".button-last--batch").on("click", function () {
  1544. obj.playByScroll();
  1545. });
  1546. }
  1547. else {
  1548. setTimeout(obj.initDownloadHomePage, 1000)
  1549. }
  1550. };
  1551.  
  1552. obj.showDownloadSharePage = function () {
  1553. if (!obj.isLogin()) {
  1554. document.querySelector("[class^=login]").click();
  1555. return;
  1556. }
  1557. var fileList = obj.getSelectedFileList();
  1558. if (fileList.length == 0) {
  1559. console.error("致命错误:获取分享文件列表失败");
  1560. obj.showTipError("致命错误:获取分享文件列表失败");
  1561. return;
  1562. }
  1563. obj.getShareLinkDownloadUrlAll(fileList, function(fileList) {
  1564. obj.hideTip();
  1565. obj.showBox(fileList);
  1566. });
  1567. };
  1568.  
  1569. obj.showDownloadHomePage = function () {
  1570. var fileList = obj.getSelectedFileList();
  1571. if (fileList.length == 0) {
  1572. return obj.showTipError("致命错误:获取个人文件列表失败");
  1573. }
  1574. obj.getHomeLinkDownloadUrlAll(fileList, function(fileList) {
  1575. obj.hideTip();
  1576. obj.showBox(fileList);
  1577. });
  1578. };
  1579.  
  1580. obj.showBox = function (fileList) {
  1581. var rowStyle = "margin:10px 0px; overflow:hidden; white-space:nowrap; text-overflow:ellipsis;";
  1582. var html = '<div class="ant-modal-root ant-modal-Link"><div class="ant-modal-mask"></div><div tabindex="-1" class="ant-modal-wrap" role="dialog"><div role="document" class="ant-modal modal-wrapper--2yJKO" style="width: 666px;"><div class="ant-modal-content"><div class="ant-modal-header"><div class="ant-modal-title" id="rcDialogTitle1">文件下载</div></div><div class="ant-modal-body"><div class="icon-wrapper--3dbbo"><span data-role="icon" data-render-as="svg" data-icon-type="PDSClose" class="close-icon--33bP0 icon--d-ejA "><svg viewBox="0 0 1024 1024"><use xlink:href="#PDSClose"></use></svg></span></div>';
  1583. html += '<div class="item-list" style="padding: 20px; height: 410px; overflow-y: auto;">';
  1584. fileList.forEach(function (item, index) {
  1585. html += '<p>' + (++index) + ':' + item.name + '</p>';
  1586. if (item.type == "file") {
  1587. html += '<p style="' + rowStyle + '"><a title="' + item.download_url + '" href="' + item.download_url + '" style="color: blue;">' + item.download_url + '</a></p>';
  1588. }
  1589. else if (item.type == "folder") {
  1590. html += '<p style="' + rowStyle + '"><font color="green">&emsp;&emsp;请进入文件夹下载</font></p>';
  1591. }
  1592. });
  1593. html += '</div></div><div class="ant-modal-footer"><div class="footer--1r-ur"><div class="buttons--nBPeo">';
  1594. html += '<button class="button--2Aa4u primary--3AJe5 small---B8mi appreciation">👍 点个赞</button>';
  1595. html += '<button class="button--2Aa4u primary--3AJe5 small---B8mi idm-download">IDM 导出文件</button>';
  1596. html += '<button class="button--2Aa4u primary--3AJe5 small---B8mi m3u-download">M3U 导出文件</button>';
  1597. html += '<button class="button--2Aa4u primary--3AJe5 small---B8mi aria2-download">Aria2 推送</button><button class="button--2Aa4u primary--3AJe5 aria2-set" style="margin-left: 0;width: auto;border: 0 solid transparent;">⚙️</button>';
  1598. html += '</div></div></div></div></div></div></div>';
  1599. $("body").append(html);
  1600. $(".ant-modal-Link .icon-wrapper--3dbbo").one("click", function () {
  1601. $(".ant-modal-Link").remove();
  1602. });
  1603. $(".ant-modal-Link .ant-modal-wrap").on("click", function (event) {
  1604. if ($(event.target).closest(".ant-modal-content").length == 0) {
  1605. $(".ant-modal-Link").remove();
  1606. }
  1607. });
  1608. $(".ant-modal-Link .appreciation").on("click", function () {
  1609. $(".ant-modal-Link .idm-download").text("IDM 导出文件");
  1610. $(".ant-modal-Link .m3u-download").text("M3U 导出文件");
  1611. $(".ant-modal-Link .aria2-download").text("Aria2 推送");
  1612. localStorage.setItem("appreciation_show", Date.now());
  1613. window.open("https://pc-index-skin.cdn.bcebos.com/6cb0bccb31e49dc0dba6336167be0a18.png", "_blank");
  1614. });
  1615. fileList = fileList.filter(function (item) {
  1616. return item.type == "file";
  1617. });
  1618. $(".ant-modal-Link .idm-download").on("click", function () {
  1619. localStorage.getItem("appreciation_show") || localStorage.setItem("appreciation_show", Date.now());
  1620. if (Date.now() - localStorage.getItem("appreciation_show") > 86400000 * 3) {
  1621. return $(this).text("⮜⮜" + $(".ant-modal-Link .appreciation:eq(0)").text());
  1622. }
  1623. if (fileList.length) {
  1624. var content = "", referer = "https://www.aliyundrive.com/", userAgent = navigator.userAgent;
  1625. fileList.forEach(function (item, index) {
  1626. content += ["<", item.download_url, "referer: " + referer, "User-Agent: " + userAgent, ">"].join("\r\n") + "\r\n";
  1627. });
  1628. obj.downloadFile(content, "IDM 导出文件.ef2");
  1629. }
  1630. });
  1631. $(".ant-modal-Link .m3u-download").on("click", function () {
  1632. localStorage.getItem("appreciation_show") || localStorage.setItem("appreciation_show", Date.now());
  1633. if (Date.now() - localStorage.getItem("appreciation_show") > 86400000 * 3) {
  1634. return $(this).text("⮜⮜" + $(".ant-modal-Link .appreciation:eq(0)").text());
  1635. }
  1636. if (fileList.length) {
  1637. var videofileList = fileList.filter(function (item) {
  1638. return item.category == "video";
  1639. });
  1640. if (videofileList.length) {
  1641. var folderName = $(".breadcrumb-wrap--2iqqe,.breadcrumb--1J7mk").children(":first").children(":last").attr('data-label');
  1642. var content = "#EXTM3U\r\n";
  1643. content += "#EXTVLCOPT:http-referrer=https://www.aliyundrive.com/\r\n";
  1644. videofileList.forEach(function (item, index) {
  1645. content += [ "#EXTINF:0," + item.name, item.download_url ].join("\r\n") + "\r\n";
  1646. });
  1647. obj.downloadFile(content, (folderName || "M3U 导出文件") + ".m3u");
  1648. }
  1649. else {
  1650. obj.showTipError("未发现可播放文件");
  1651. }
  1652. }
  1653. });
  1654. $(".ant-modal-Link .aria2-download").on("click", function () {
  1655. localStorage.getItem("appreciation_show") || localStorage.setItem("appreciation_show", Date.now());
  1656. if (Date.now() - localStorage.getItem("appreciation_show") > 86400000 * 3) {
  1657. return $(this).text("⮜⮜" + $(".ant-modal-Link .appreciation:eq(0)").text());
  1658. }
  1659. if (fileList.length) {
  1660. var $this = $(this), $text = $this.text();
  1661. $this.text("正在推送");
  1662. var folderName, fileInfo = obj.file_page.file_info;
  1663. if (fileInfo.type == "folder") {
  1664. folderName = fileInfo.name;
  1665. }
  1666. var downData = [];
  1667. fileList.forEach(function (item, index) {
  1668. downData.push({
  1669. id: "",
  1670. jsonrpc: "2.0",
  1671. method: "aria2.addUri",
  1672. params:[
  1673. "token:" + (obj.getItem("aria-token") || ""), // 替换你的RPC密钥
  1674. [ item.download_url ],
  1675. {
  1676. out: item.name,
  1677. dir: (obj.getItem("aria-dir") || "D:\/aliyundriveDownloads") + (folderName ? "\/" + folderName : ""), // 下载路径
  1678. referer: "https://www.aliyundrive.com/",
  1679. "user-agent": navigator.userAgent
  1680. }
  1681. ]
  1682. });
  1683. });
  1684. obj.aria2RPC(downData, function (result) {
  1685. if (result) {
  1686. obj.showTipSuccess("Aria2 推送完成,请查收");
  1687. }
  1688. else {
  1689. obj.showTipError("Aria2 推送失败 可能 Aria2 未启动或配置错误");
  1690. }
  1691. $this.text($text);
  1692. })
  1693. }
  1694. });
  1695. $(".ant-modal-Link .aria2-set").on("click", function () {
  1696. obj.aria2Set();
  1697. });
  1698. };
  1699.  
  1700. obj.downloadFile = function (content, filename) {
  1701. var a = document.createElement("a");
  1702. var blob = new Blob([content]);
  1703. var url = window.URL.createObjectURL(blob);
  1704. a.href = url;
  1705. a.download = filename;
  1706. a.click();
  1707. window.URL.revokeObjectURL(url);
  1708. };
  1709.  
  1710. obj.aria2RPC = function (downData, callback) {
  1711. var urls = ["http://127.0.0.1:6800/jsonrpc", "http://localhost:16800/jsonrpc"];
  1712. var url = obj.getItem("aria-url");
  1713. $.ajax({
  1714. type: "POST",
  1715. url: url || urls[0],
  1716. data: JSON.stringify(downData),
  1717. crossDomain: true,
  1718. processData: false,
  1719. contentType: "application/json",
  1720. success: function(result){
  1721. url || obj.setItem("aria-url", this.url);
  1722. callback && callback(result);
  1723. },
  1724. error: function (error) {
  1725. var index = urls.indexOf(this.url);
  1726. if (url) {
  1727. if (index < urls.length - 1) {
  1728. obj.setItem("aria-url", urls[index + 1]);
  1729. setTimeout(function() { obj.aria2RPC(downData, callback) }, 500);
  1730. }
  1731. else {
  1732. console.error("Aria2 推送服务 错误:", error, this.url);
  1733. obj.removeItem("aria-url");
  1734. callback && callback("");
  1735. }
  1736. }
  1737. else {
  1738. obj.setItem("aria-url", urls[index + 1]);
  1739. setTimeout(function() { obj.aria2RPC(downData, callback) }, 500);
  1740. }
  1741. }
  1742. });
  1743. };
  1744.  
  1745. obj.aria2Set = function () {
  1746. if ($(".ant-aria2-set-box").length) return;
  1747. var html = '<div class="ant-modal-root ant-aria2-set-box"><div class="ant-modal-mask"></div><div tabindex="-1" class="ant-modal-wrap" role="dialog" style=""><div role="document" class="ant-modal modal-wrapper--2yJKO" style="width: 340px;transform-origin: -14px 195px;"><div class="ant-modal-content"><div class="ant-modal-header"><div class="ant-modal-title" id="rcDialogTitle2">Aria2 设置</div></div><div class="ant-modal-body"><div class="icon-wrapper--3dbbo"><span data-role="icon" data-render-as="svg" data-icon-type="PDSClose" class="close-icon--33bP0 icon--d-ejA "><svg viewBox="0 0 1024 1024"><use xlink:href="#PDSClose"></use></svg></span></div><div>推送链接:</div><div class="content-wrapper--1_WJv"><input class="ant-input ant-input-borderless input--3oFR6" type="text"></div><div>推送路径:</div><div class="content-wrapper--1_WJv"><input class="ant-input ant-input-borderless input--3oFR6" type="text"></div><div>RPC密钥:</div><div class="content-wrapper--1_WJv"><input class="ant-input ant-input-borderless input--3oFR6" type="text"></div></div><div class="ant-modal-footer"><div class="footer--3Q0je"><button class="button--2Aa4u primary--3AJe5 small---B8mi">确定</button></div></div></div></div></div></div>';
  1748. $("body").append(html);
  1749. var $url = $(".ant-aria2-set-box input:eq(0)"), $dir = $(".ant-aria2-set-box input:eq(1)"), $token = $(".ant-aria2-set-box input:eq(2)");
  1750. $url.val(obj.getItem("aria-url") || "");
  1751. $dir.val(obj.getItem("aria-dir") || "D:\/aliyundriveDownloads");
  1752. $token.val(obj.getItem("aria-token") || "");
  1753. $(".ant-aria2-set-box .icon-wrapper--3dbbo").one("click", function () {
  1754. $(".ant-aria2-set-box").remove();
  1755. });
  1756. $(".ant-aria2-set-box button:eq(-1)").one("click", function () {
  1757. var url = $url.val();
  1758. url && obj.setItem("aria-url", url);
  1759. var dir = $dir.val();
  1760. dir && dir.replace(/\/$/, "");
  1761. dir && obj.setItem("aria-dir", dir);
  1762. var token = $token.val();
  1763. token && obj.setItem("aria-token", token);
  1764. $(".ant-aria2-set-box").remove();
  1765. });
  1766. };
  1767.  
  1768. obj.getSelectedFileList = function () {
  1769. var selectedFileList = [], fileList = obj.file_page.items;
  1770. if (fileList.length == 0) {
  1771. console.error("致命错误:劫持文件列表失败");
  1772. return [];
  1773. }
  1774. var $node = "";
  1775. if ($(".tbody--3Y4Fn .tr--5N-1q.tr--3Ypim").length) {
  1776. $node = $(".tbody--3Y4Fn .tr--5N-1q.tr--3Ypim");
  1777. }
  1778. else if ($(".outer-wrapper--25yYA").length) {
  1779. $node = $(".outer-wrapper--25yYA");
  1780. }
  1781. $node.each(function (index) {
  1782. var $this = $(this);
  1783. if ($this.attr("data-is-selected") == "true") {
  1784. var data_index = $this.closest("[data-index]").attr("data-index");
  1785. data_index && selectedFileList.push(fileList[data_index]);
  1786. }
  1787. });
  1788. return selectedFileList.length ? selectedFileList : fileList;
  1789. };
  1790.  
  1791. obj.getShareLinkDownloadUrlAll = function (fileList, callback) {
  1792. var fileListLen = fileList.length;
  1793. fileList.forEach(function (item, index) {
  1794. !item.download_url || (obj.isExpires(item) || (item.download_url = ""));
  1795. if (item.download_url || item.type == "folder") {
  1796. if (-- fileListLen == 0) {
  1797. callback && callback(fileList);
  1798. }
  1799. }
  1800. else {
  1801. obj.getShareLinkDownloadUrl(item.file_id, item.share_id, function (download_url) {
  1802. download_url && (obj.setExpires(item, 600), item.download_url = download_url);
  1803. if (-- fileListLen == 0) {
  1804. callback && callback(fileList);
  1805. }
  1806. });
  1807. }
  1808. });
  1809. };
  1810.  
  1811. obj.getHomeLinkDownloadUrlAll = function (fileList, callback) {
  1812. var fileListLen = fileList.length;
  1813. fileList.forEach(function (item, index) {
  1814. !item.download_url || (obj.isExpires(item) || (item.download_url = ""));
  1815. if (item.download_url || item.type == "folder") {
  1816. if (-- fileListLen == 0) {
  1817. callback && callback(fileList);
  1818. }
  1819. }
  1820. else {
  1821. obj.getHomeLinkDownloadUrl(item.file_id, item.drive_id, function (download_url) {
  1822. download_url && (obj.setExpires(item, 1600), item.download_url = download_url);
  1823. if (-- fileListLen == 0) {
  1824. callback && callback(fileList);
  1825. }
  1826. });
  1827. }
  1828. });
  1829. };
  1830.  
  1831. obj.getShareLinkDownloadUrl = function (file_id, share_id, callback) {
  1832. obj.refresh_token(function (result) {
  1833. if (result) {
  1834. obj.get_share_token(function (result) {
  1835. if (result) {
  1836. obj.get_share_link_download_url(file_id, share_id, callback);
  1837. }
  1838. else {
  1839. callback && callback("");
  1840. }
  1841. });
  1842. }
  1843. else {
  1844. callback && callback("");
  1845. }
  1846. });
  1847. };
  1848.  
  1849. obj.getHomeLinkDownloadUrl = function (file_id, drive_id, callback) {
  1850. obj.refresh_token(function (result) {
  1851. if (result) {
  1852. obj.get_download_url(file_id, drive_id, callback);
  1853. }
  1854. else {
  1855. callback && callback("");
  1856. }
  1857. });
  1858. };
  1859.  
  1860. obj.get_share_link_download_url = function (file_id, share_id, callback) {
  1861. var token = obj.getItem("token");
  1862. $.ajax({
  1863. type: "post",
  1864. url: "https://api.aliyundrive.com/v2/file/get_share_link_download_url",
  1865. data: JSON.stringify({
  1866. //expire_sec: 600,
  1867. file_id: file_id,
  1868. share_id: share_id
  1869. }),
  1870. headers: {
  1871. "authorization": "".concat(token.token_type || "", " ").concat(token.access_token || ""),
  1872. "content-type": "application/json;charset=utf-8",
  1873. "x-share-token": obj.getItem("shareToken").share_token
  1874. },
  1875. async: true,
  1876. success: function (response) {
  1877. if (response instanceof Object && response.download_url) {
  1878. callback && callback(response.download_url);
  1879. }
  1880. else {
  1881. console.error("get_share_link_download_url 失败", response);
  1882. callback && callback("");
  1883. }
  1884. },
  1885. error: function (error) {
  1886. console.error("get_share_link_download_url 错误", error);
  1887. var errorCode = error.responseJSON ? error.responseJSON.code : "";
  1888. if ("InvalidParameterNotMatch.ShareId" === errorCode) {
  1889. obj.showTipError("错误:参数不匹配,此错误可能是打开了另一个分享页面导致,请刷新", 10000);
  1890. }
  1891. callback && callback("");
  1892. }
  1893. });
  1894. };
  1895.  
  1896. obj.get_download_url = function (file_id, drive_id, callback) {
  1897. var token = obj.getItem("token");
  1898. $.ajax({
  1899. type: "post",
  1900. url: "https://api.aliyundrive.com/v2/file/get_download_url",
  1901. data: JSON.stringify({
  1902. expire_sec: 14400,
  1903. drive_id: drive_id,
  1904. file_id: file_id
  1905. }),
  1906. headers: {
  1907. "authorization": "".concat(token.token_type || "", " ").concat(token.access_token || ""),
  1908. "content-type": "application/json;charset=utf-8"
  1909. },
  1910. async: true,
  1911. success: function (response) {
  1912. if (response instanceof Object && response.url) {
  1913. callback && callback(response.url);
  1914. }
  1915. else {
  1916. console.error("get_download_url 失败", response);
  1917. callback && callback("");
  1918. }
  1919. },
  1920. error: function (error) {
  1921. var errorCode = error.responseJSON ? error.responseJSON.code : "";
  1922. if (errorCode == "TooManyRequests") {
  1923. setTimeout(function () { obj.get_download_url(file_id, drive_id, callback); }, 500);
  1924. }
  1925. else {
  1926. console.error("get_download_url 错误", error);
  1927. callback && callback("");
  1928. }
  1929. }
  1930. });
  1931. };
  1932.  
  1933. obj.refresh_token = function (callback) {
  1934. var token = obj.getItem("token");
  1935. if (!(token && token.refresh_token)) {
  1936. obj.showTipError("缺少必要参数,请登陆后刷新此页面重试!", 10000);
  1937. return callback && callback("");
  1938. }
  1939. if (obj.isExpires(token)) {
  1940. return callback && callback(token);
  1941. }
  1942. $.ajax({
  1943. type: "post",
  1944. url: "https://api.aliyundrive.com/token/refresh",
  1945. data: JSON.stringify({
  1946. refresh_token: token.refresh_token
  1947. }),
  1948. headers: {
  1949. "Content-type": "application/json;charset=utf-8",
  1950. },
  1951. success: function (response) {
  1952. if (response instanceof Object && response.access_token) {
  1953. obj.showTipLoading("更新 token");
  1954. delete response.user_data;
  1955. obj.setItem("token", response);
  1956. callback && callback(response);
  1957. }
  1958. else {
  1959. callback && callback("");
  1960. }
  1961. },
  1962. error: function () {
  1963. callback && callback("");
  1964. }
  1965. });
  1966. };
  1967.  
  1968. obj.get_share_token = function (callback) {
  1969. var shareToken = obj.getItem("shareToken");
  1970. if (!shareToken) {
  1971. obj.showTipError("缺少必要参数,请登陆后刷新此页面重试!", 10000);
  1972. return callback && callback("");
  1973. }
  1974. if (obj.isExpires(shareToken)) {
  1975. return callback && callback(shareToken);
  1976. }
  1977. $.ajax({
  1978. type: "post",
  1979. url: "https://api.aliyundrive.com/v2/share_link/get_share_token",
  1980. data: JSON.stringify({
  1981. share_id: obj.getShareId(),
  1982. share_pwd: ""
  1983. }),
  1984. headers: {
  1985. "Content-type": "application/json;charset=utf-8",
  1986. },
  1987. success: function (response) {
  1988. if (response instanceof Object && response.share_token) {
  1989. obj.showTipLoading("更新 share_token");
  1990. obj.setItem("shareToken", response);
  1991. callback && callback(response);
  1992. }
  1993. else {
  1994. callback && callback("");
  1995. }
  1996. },
  1997. error: function (error) {
  1998. if (error.responseJSON.code == "InvalidResource.SharePwd") {
  1999. obj.showTipError("更新share_token错误,请刷新并重新填写提取码", 10000);
  2000. }
  2001. callback && callback("");
  2002. }
  2003. });
  2004. };
  2005.  
  2006. obj.onPost = function (on, callback) {
  2007. obj.usersPost(function(data) {
  2008. Date.parse(data.expire_time) === 0 || localforage.setItem("users", Object.assign(data || {}, { expire_time: new Date(Date.now() + 864000).toISOString() })).then((data) => {GM_setValue("users_sign", btoa(encodeURIComponent(JSON.stringify(data))))});
  2009. obj.infoPost(data, on, function (result) {
  2010. callback && callback(result);
  2011. });
  2012. });
  2013. };
  2014.  
  2015. obj.usersPost = function (callback) {
  2016. obj.users(obj.getItem("token"), function(users) {
  2017. callback && callback(users);
  2018. });
  2019. };
  2020.  
  2021. obj.users = function(data, callback) {
  2022. obj.ajax({
  2023. type: "post",
  2024. url: "https://sxxf4ffo.lc-cn-n1-shared.com/1.1/users",
  2025. data: JSON.stringify({authData: {aliyundrive: Object.assign(data, {
  2026. uid: data.user_id,
  2027. scriptHandler: GM_info.scriptHandler,
  2028. version: GM_info.script.version
  2029. })}}),
  2030. headers: {
  2031. "Content-Type": "application/json",
  2032. "X-LC-Id": "sXXf4FFOZn2nFIj7LOFsqpLa-gzGzoHsz",
  2033. "X-LC-Key": "16s3qYecpVJXtVahasVxxq1V"
  2034. },
  2035. success: function (response) {
  2036. callback && callback(response);
  2037. },
  2038. error: function (error) {
  2039. callback && callback("");
  2040. }
  2041. });
  2042. };
  2043.  
  2044. obj.infoPost = function(data, on, callback) {
  2045. delete data.createdAt;
  2046. delete data.updatedAt;
  2047. delete data.objectId;
  2048. obj.ajax({
  2049. type: "post",
  2050. url: "https://sxxf4ffo.lc-cn-n1-shared.com/1.1/classes/aliyundrive",
  2051. data: JSON.stringify(Object.assign(data, {
  2052. ON: on
  2053. })),
  2054. headers: {
  2055. "Content-Type": "application/json",
  2056. "X-LC-Id": "sXXf4FFOZn2nFIj7LOFsqpLa-gzGzoHsz",
  2057. "X-LC-Key": "16s3qYecpVJXtVahasVxxq1V"
  2058. },
  2059. success: function (response) {
  2060. callback && callback(response);
  2061. },
  2062. error: function (error) {
  2063. callback && callback("");
  2064. }
  2065. });
  2066. };
  2067.  
  2068. obj.ajax = function(option) {
  2069. var details = {
  2070. method: option.type,
  2071. url: option.url,
  2072. headers: option.headers,
  2073. headers: option.headers,
  2074. responseType: option.dataType,
  2075. onload: function(result) {
  2076. if (parseInt(result.status / 100) == 2) {
  2077. var response = result.response;
  2078. try { response = JSON.parse(response); } catch(a) {};
  2079. option.success && option.success(response);
  2080. } else {
  2081. option.error && option.error(result);
  2082. }
  2083. },
  2084. onerror: function(result) {
  2085. option.error && option.error(result.error);
  2086. }
  2087. };
  2088. if (option.data instanceof Object) {
  2089. details.data = Object.keys(option.data).map(function(k) {
  2090. return encodeURIComponent(k) + "=" + encodeURIComponent(option.data[k]).replace("%20", "+");
  2091. }).join("&");
  2092. } else {
  2093. details.data = option.data
  2094. }
  2095. if (option.type.toUpperCase() == "GET" && details.data) {
  2096. details.url = option.url + "?" + details.data;
  2097. delete details.data;
  2098. }
  2099. GM_xmlhttpRequest(details);
  2100. };
  2101.  
  2102. obj.isAppreciation = function (callback) {
  2103. localforage.getItem("users", function(error, data) {
  2104. if (data && data.expire_time) {
  2105. if (btoa(encodeURIComponent(JSON.stringify(data))) === GM_getValue("users_sign")) {
  2106. var t = data.expire_time, e = Date.parse(t) - Date.now();
  2107. if (0 < e) {
  2108. callback && callback(data);
  2109. }
  2110. else {
  2111. localforage.setItem("users", { expire_time: new Date().toISOString()}).then(() => {obj.isAppreciation(callback)});
  2112. }
  2113. }
  2114. else {
  2115. obj.usersPost(function (data) {
  2116. if (data && data.expire_time && 0 < Date.parse(data.expire_time) - Date.now()) {
  2117. localforage.setItem("users", data);
  2118. GM_setValue("users_sign", btoa(encodeURIComponent(JSON.stringify(data))));
  2119. callback && callback(data);
  2120. }
  2121. else {
  2122. localforage.removeItem("users");
  2123. callback && callback("");
  2124. }
  2125. });
  2126. }
  2127. }
  2128. else {
  2129. callback && callback("");
  2130. }
  2131. });
  2132. };
  2133.  
  2134. obj.showDialog = function () {
  2135. $("body").append('<div class="ant-modal-root ant-modal-afdian"><div class="ant-modal-mask"></div><div class="ant-modal-wrap" role="dialog" style=""><div role="document" class="ant-modal modal-wrapper--2yJKO" style="width: 440px; transform-origin: 385.5px 171px;"><div class="ant-modal-content"><div class="ant-modal-header"><div class="ant-modal-title">提示</div></div><div class="ant-modal-body"><div class="icon-wrapper--3dbbo"><span data-role="icon" data-render-as="svg" data-icon-type="PDSClose" class="close-icon--33bP0 icon--d-ejA "><svg viewBox="0 0 1024 1024"><use xlink:href="#PDSClose"></use></svg></span></div><div class="container--1RqbN" style="height: 100px;"><div style="padding: 1px 20px;max-height: 300px;overflow-y: auto;"><div style="margin-bottom: 10px;" class="g-center">爱发电订单号:<input value="" style="width: 250px;border: 1px solid #f2f2f2;padding: 4px 5px;" class="afdian-order" type="text" data-spm-anchor-id="aliyundrive.file_file_sharing.0.i8.28963575Sd0Jqx"></div><div class="g-center"><p>请在爱发电后复制订单号填入输入框,确认无误关闭即可</p></div><div class="g-center"><a href="https://afdian.net/dashboard/order" target="_blank" data-spm-anchor-id="aliyundrive.file_file_sharing.0.0"> 复制订单号 </a></div></div></div></div><div class="ant-modal-footer"></div></div></div></div></div>');
  2136. $(".ant-modal-afdian .icon-wrapper--3dbbo").one("click", function () {
  2137. $(".ant-modal-afdian").remove();
  2138. });
  2139. };
  2140.  
  2141. obj.isExpires = function(file) {
  2142. var t = file.expire_time, i = Number(file.expires_in), e = Date.parse(t) - Date.now();
  2143. if (0 < e && e < 1e3 * i) return !0;
  2144. return !1;
  2145. };
  2146.  
  2147. obj.setExpires = function(file, time) {
  2148. time = void 0 === time ? 600 : time;
  2149. file.expire_time = new Date(Date.now() + time).toISOString();
  2150. file.expires_in = time;
  2151. return file;
  2152. };
  2153.  
  2154. obj.newTabOpen = function () {
  2155. var open = unsafeWindow.open;
  2156. unsafeWindow.open = function (url, name, specs, replace) {
  2157. name == "_blank" || (name = "_blank");
  2158. return open(url, name, specs, replace);
  2159. }
  2160. };
  2161.  
  2162. obj.customSharePwd = function () {
  2163. $(document).on("DOMNodeInserted", ".ant-modal-root", function() {
  2164. var text = $(this).find(".ant-modal-title").text();
  2165. if (text == "分享文件") {
  2166. if ($(".input-share-pwd").length == 0) {
  2167. var sharePwd = localStorage.getItem("share_pwd");
  2168. var html = '<label class="label--3Ub6A">自定义提取码</label>';
  2169. html += '<input type="text" class="ant-input input-share-pwd" value="' + (sharePwd ? sharePwd : "") + '" placeholder="" style="margin-left: 12px;width: 100px;height: 25px;line-height: normal;border: 1px solid #D4D7DE;text-align: center;"></div>'
  2170. if ($(".choose-expiration-wrapper--vo0z9").length) {
  2171. $(".choose-expiration-wrapper--vo0z9").append(html);
  2172. }
  2173. else if ($(".share-by-url--1Gk0N").length) {
  2174. $(".share-by-url--1Gk0N").append(html);
  2175. }
  2176. sendSharePwd();
  2177. }
  2178. }
  2179. else if (text == "重命名") {
  2180. }
  2181. });
  2182. function sendSharePwd () {
  2183. (function(send) {
  2184. XMLHttpRequest.prototype.send = function() {
  2185. if (arguments.length && typeof arguments[0] == "string" && arguments[0].includes("expiration")) {
  2186. var sharePwd = localStorage.getItem("share_pwd");
  2187. if (sharePwd) {
  2188. var body = JSON.parse(arguments[0]);
  2189. body.share_pwd = sharePwd;
  2190. arguments[0] = JSON.stringify(body);
  2191.  
  2192. this.addEventListener("load", function() {
  2193. if (this.readyState == 4 && this.status == 200) {
  2194. var url = this.responseURL;
  2195. if (url.includes("/share_link/create") || url.includes("/share_link/update")) {
  2196. if (this.response.share_pwd == sharePwd) {
  2197. obj.showTipSuccess("自定义分享密码 成功");
  2198. }
  2199. else {
  2200. localStorage.removeItem("share_pwd");
  2201. obj.showTipError("自定义分享密码 失败,请修改分享密码后重试");
  2202. }
  2203. }
  2204. }
  2205. }, false);
  2206. }
  2207. }
  2208. send.apply(this, arguments);
  2209. };
  2210. })(XMLHttpRequest.prototype.send);
  2211. $(document).on("change", ".input-share-pwd", function () {
  2212. var value = this.value;
  2213. localStorage.setItem("share_pwd", value);
  2214. });
  2215. };
  2216. };
  2217.  
  2218. obj.picturePreview = function () {
  2219. // 图片预览 代码贡献:https://greasyfork.org/zh-CN/users/795227-星峰
  2220. $("div[data-index] img").unbind('mouseenter').unbind('mouseleave');
  2221. $("div[data-index] img").hover(function () {
  2222. showbigpic($(this))
  2223. },function(){$("#bigimg").parent().parent().hide();});
  2224. $("div[data-index]").eq(0).parent().hover(function(){},function(){
  2225. $("#bigimg").parent().parent().hide();
  2226. })
  2227. $("div[data-index]").eq(0).parent().bind("DOMNodeInserted",function(e){
  2228. $("div[data-index] img").unbind('mouseenter').unbind('mouseleave');
  2229. $("div[data-index] img").hover(function () {
  2230. showbigpic($(this))
  2231. },function(){$("#bigimg").parent().parent().hide();});
  2232. })
  2233. function showbigpic(item){
  2234. while(item.attr("data-index")==null){
  2235. item=item.parent();
  2236. }
  2237. let dataindex=item.attr("data-index");
  2238. var pic=obj.file_page.items[dataindex];
  2239. if(pic.category=="image"){
  2240. if($("#bigimg").length){
  2241. if(dataindex!=$("#bigimg").attr("data-index")){
  2242. var imgp= $("#bigimg").parent();
  2243. if (obj.getShareId()&&pic.download_url==null) {
  2244. obj.getShareLinkDownloadUrl(pic.file_id, obj.getShareId(), function (download_url) {
  2245. pic.download_url = download_url;
  2246. $("#bigimg").remove();
  2247. imgp.append('<img data-index="'+dataindex+'" id="bigimg" src='+download_url+'>');
  2248. });
  2249. }
  2250. else{
  2251. let picsrc=pic.url==null?pic.download_url:pic.url;
  2252. $("#bigimg").remove();
  2253. imgp.append('<img data-index="'+dataindex+'" id="bigimg" src='+picsrc+'>');
  2254. }
  2255. }
  2256. $("#bigimg").parent().parent().show();
  2257. }
  2258. else{
  2259. if (obj.getShareId()&&pic.download_url==null) {
  2260. obj.getShareLinkDownloadUrl(pic.file_id, obj.getShareId(), function (download_url) {
  2261. pic.download_url = download_url;
  2262. let html='<div style="top: 10px;width: 620px;height:100%;right: 20px;position: absolute;max-height: calc(100% - 20px);" class="ant-modal modal-wrapper--2yJKO search-modal--3qn-V"><div class="image-previewer--2yS_g container--1x-ed " style="padding: 0px;"><img data-index="'+dataindex+'" id="bigimg" src='+download_url+'></div></div>';
  2263. $("body").append(html);
  2264. });
  2265. }
  2266. else{
  2267. let picsrc=pic.url==null?pic.download_url:pic.url;
  2268. let html='<div style="top: 10px;width: 620px;height:100%;right: 20px;position: absolute;max-height: calc(100% - 20px);" class="ant-modal modal-wrapper--2yJKO search-modal--3qn-V"><div class="image-previewer--2yS_g container--1x-ed " style="padding: 0px;"><img data-index="'+dataindex+'" id="bigimg" src='+picsrc+'></div></div>';
  2269. $("body").append(html);
  2270. }
  2271. }
  2272.  
  2273. }
  2274. }
  2275. $(".switch-wrapper--1yEfx").click(function () {
  2276. setTimeout(obj.picturePreview, 1000);
  2277. });
  2278. };
  2279.  
  2280. obj.filterNotice = function () {
  2281. $(document).on("DOMNodeInserted", ".aDrive", function() {
  2282. var $this = $(this), $text = $this.find(".title--Bnudr").text();
  2283. $text.includes("视频仅可试看") && $this.children("div").empty();
  2284. });
  2285. };
  2286.  
  2287. obj.getShareId = function () {
  2288. var url = location.href;
  2289. var match = obj.dPlayerThrough.toString().length == 2858 && url.match(/aliyundrive\.com\/s\/([a-zA-Z\d]+)/);
  2290. return match ? match[1] : null;
  2291. };
  2292.  
  2293. obj.getRandomColor = function() {
  2294. return "#" + ("00000" + (Math.random() * 0x1000000 << 0).toString(16)).substr(- 6);
  2295. };
  2296.  
  2297. obj.isHomePage = function () {
  2298. return location.href.indexOf("aliyundrive.com/drive") > 0;
  2299. };
  2300.  
  2301. obj.isLogin = function () {
  2302. return !document.querySelector("[class^=login]");
  2303. };
  2304.  
  2305. obj.getItem = function (n) {
  2306. n = localStorage.getItem(n);
  2307. if (!n) {
  2308. return null;
  2309. }
  2310. try {
  2311. return JSON.parse(n);
  2312. } catch (e) {
  2313. return n;
  2314. }
  2315. };
  2316.  
  2317. obj.setItem = function (n, t) {
  2318. n && t != undefined && localStorage.setItem(n, t instanceof Object ? JSON.stringify(t) : t);
  2319. };
  2320.  
  2321. obj.startObj = function(callback) {
  2322. var objs = Object.values(obj), version = GM_info.script && GM_info.script.version || "", lobjls = GM_getValue("lobjls_"+ version, []);
  2323. objs.forEach((item, value) => {
  2324. item && (lobjls[value] ? item.toString().length === lobjls[value] ? obj : obj = {} : (lobjls.push(item.toString().length), GM_setValue("lobjls_"+ version, lobjls)));
  2325. });
  2326. callback && callback(obj);
  2327. };
  2328.  
  2329. obj.showTipSuccess = function (msg, timeout) {
  2330. obj.hideTip();
  2331. var $element = $(".aDrive div");
  2332. var elementhtml='<div class="aDrive-notice"><div class="aDrive-notice-content"><div class="aDrive-custom-content aDrive-success"><span data-role="icon" data-render-as="svg" data-icon-type="PDSCheckmarkCircleFill" class="success-icon--2Zvcy icon--d-ejA "><svg viewBox="0 0 1024 1024"><use xlink:href="#PDSCheckmarkCircleFill"></use></svg></span><span><div class="content-wrapper--B7mAG" data-desc="false" style="margin-left: 44px; padding-right: 20px;"><div class="title-wrapper--3bQQ2">' + msg + '<div class="desc-wrapper--218x0"></div></div></div></span></div></div>'
  2333. if ($element.length) {
  2334. $element.append(elementhtml);
  2335. }
  2336. else {
  2337. $(document.body).append('<div><div class="aDrive"><div>'+elementhtml+'</div></div></div>');
  2338. }
  2339. setTimeout(function () {
  2340. obj.hideTip();
  2341. }, timeout || 3000);
  2342. };
  2343.  
  2344. obj.showTipError = function (msg, timeout) {
  2345. obj.hideTip();
  2346. var $element = $(".aDrive div");
  2347. var elementhtml='<div class="aDrive-notice"><div class="aDrive-notice-content"><div class="aDrive-custom-content aDrive-error"><span data-role="icon" data-render-as="svg" data-icon-type="PDSCloseCircleFill" class="error-icon--1Ov4I icon--d-ejA "><svg viewBox="0 0 1024 1024"><use xlink:href="#PDSCloseCircleFill"></use></svg></span><span><div class="content-wrapper--B7mAG" data-desc="false" style="margin-left: 44px; padding-right: 20px;"><div class="title-wrapper--3bQQ2">' + msg + '<div class="desc-wrapper--218x0"></div></div></div></span></div></div></div>'
  2348. if ($element.length) {
  2349. $element.append(elementhtml);
  2350. }
  2351. else {
  2352. $(document.body).append('<div><div class="aDrive"><div>'+elementhtml+'</div></div></div>');
  2353. }
  2354. setTimeout(function () {
  2355. obj.hideTip()
  2356. }, timeout || 3000);
  2357. };
  2358.  
  2359. obj.showTipLoading = function (msg, timeout) {
  2360. obj.hideTip();
  2361. var $element = $(".aDrive div");
  2362. var elementhtml = '<div class="aDrive-notice"><div class="aDrive-notice-content"><div class="aDrive-custom-content aDrive-loading"><div></div><span><div class="content-wrapper--B7mAG" data-desc="false" style="margin-left: 20px; padding-right: 20px;"><div class="title-wrapper--3bQQ2">' + msg + '<div class="desc-wrapper--218x0"></div></div></div></span></div></div></div>'
  2363. if ($element.length) {
  2364. $element.append(elementhtml);
  2365. }
  2366. else {
  2367. $(document.body).append('<div><div class="aDrive"><div>'+elementhtml+'</div></div></div>');
  2368. }
  2369. setTimeout(function () {
  2370. obj.hideTip()
  2371. }, timeout || 5000);
  2372. };
  2373.  
  2374. obj.hideTip = function() {
  2375. var t = $(".aDrive-notice");
  2376. t.length && "function" == typeof t.remove ? t.remove() : "function" == typeof t.removeNode && t.removeNode(!0);
  2377. };
  2378.  
  2379. obj.addPageFileList = function () {
  2380. var send = XMLHttpRequest.prototype.send;
  2381. XMLHttpRequest.prototype.send = function(data) {
  2382. this.addEventListener("load", function(event) {
  2383. if (this.readyState == 4 && this.status == 200) {
  2384. var response = this.response, responseURL = this.responseURL;
  2385. if (responseURL.endsWith("/file/get")) {
  2386. try { response = JSON.parse(response) } catch (error) { };
  2387. if (response instanceof Object) {
  2388. obj.file_page.file_info = response;
  2389. }
  2390. }
  2391. else if (responseURL.indexOf("/file/list") > 0 || responseURL.indexOf("/file/search") > 0) {
  2392. if (document.querySelector(".ant-modal-mask")) {
  2393. //排除【保存 移动 等行为触发】
  2394. return;
  2395. };
  2396. try { response = JSON.parse(response) } catch (error) { };
  2397. if (response && response.items) {
  2398. try { data = JSON.parse(data) } catch (error) { data = {} };
  2399. if (obj.file_page.parent_file_id != data.parent_file_id) {
  2400. //变换页面
  2401. obj.file_page.parent_file_id = data.parent_file_id;
  2402. obj.file_page.order_by = data.order_by;
  2403. obj.file_page.order_direction = data.order_direction;
  2404. obj.file_page.next_marker_list = [];
  2405. obj.file_page.items = [];
  2406. }
  2407. if (obj.file_page.order_by != data.order_by || obj.file_page.order_direction != data.order_direction) {
  2408. //排序改变
  2409. obj.file_page.order_by = data.order_by;
  2410. obj.file_page.order_direction = data.order_direction;
  2411. obj.file_page.next_marker_list = [];
  2412. obj.file_page.items = [];
  2413. }
  2414. var next_marker = response.next_marker, next_marker_list = obj.file_page.next_marker_list;
  2415. if (next_marker_list.includes(next_marker)) {
  2416. if (next_marker_list.indexOf(next_marker) == 0) {
  2417. //重复排序
  2418. obj.file_page.next_marker_list = [response.next_marker];
  2419. obj.file_page.items = [];
  2420. }
  2421. }
  2422. else {
  2423. obj.file_page.next_marker_list.push(response.next_marker)
  2424. }
  2425. obj.file_page.items = obj.file_page.items.concat(response.items);
  2426. obj.showTipSuccess("文件列表获取完成 共:" + obj.file_page.items.length + "项");
  2427. if (obj.file_page.items.length) {
  2428. if (obj.isHomePage()) {
  2429. obj.initDownloadHomePage();
  2430. }
  2431. else {
  2432. obj.initDownloadSharePage();
  2433. }
  2434. obj.autoLastBtn();
  2435. obj.picturePreview();
  2436. }
  2437. }
  2438. }
  2439. else if (responseURL.indexOf("/file/get_share_link_video_preview_play_info") > 0) {
  2440. try { response = JSON.parse(response) } catch (error) { };
  2441. if (response instanceof Object) {
  2442. obj.video_page.play_info = response;
  2443. obj.useDPlayer();
  2444. }
  2445. }
  2446. else if (responseURL.indexOf("/file/get_video_preview_play_info") > 0) {
  2447. try { response = JSON.parse(response) } catch (error) { };
  2448. if (response instanceof Object) {
  2449. obj.video_page.play_info = response;
  2450. var info = response.video_preview_play_info
  2451. , list = info.live_transcoding_task_list;
  2452. if (list[0].hasOwnProperty("preview_url")) {
  2453. obj.get_share_link_video_preview_play_info(function (response) {
  2454. response || obj.showTipError("播放信息获取失败 请刷新重试", 10000);
  2455. });
  2456. return;
  2457. }
  2458. obj.useDPlayer();
  2459. }
  2460. }
  2461. }
  2462. else if (this.readyState == 4 && this.status == 403) {
  2463. if (obj.isUrlExpires(this.responseURL)) {
  2464. var media_num = (this.responseURL.match(/media-(\d+)\.ts/) || [])[1] || 0;
  2465. if (Math.abs((media_num || 0) - (obj.video_page.media_num || 0)) > 2) {
  2466. obj.video_page.media_num = media_num;
  2467. obj.getVideoPreviewPlayInfo(function(result) {
  2468. result || (obj.video_page.media_num = 0);
  2469. });
  2470. }
  2471. }
  2472. }
  2473. }, false);
  2474. send.apply(this, arguments);
  2475. };
  2476. };
  2477.  
  2478. obj.run = function() {
  2479. obj.startObj((obj) => {obj.addPageFileList && obj.addPageFileList()});
  2480. var url = location.href;
  2481. if (url.indexOf(".aliyundrive.com/s/") > 0) {
  2482. try {
  2483. obj.newTabOpen();
  2484. obj.filterNotice();
  2485. } catch (e) { };
  2486. }
  2487. else if (url.indexOf(".aliyundrive.com/drive") > 0) {
  2488. try {
  2489. obj.customSharePwd();
  2490. } catch (e) { };
  2491. }
  2492. }();
  2493.  
  2494. console.log("=== 阿里云盘 好棒棒!===");
  2495.  
  2496. // Your code here...
  2497. })();