您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
1.自动播放下一集 2.收藏功能 3.历史观看记录 4.去广告 5.播放记录 6.小窗口播放 7.下载视频
当前为
// ==UserScript== // @name ddrk低端影视助手 // @namespace king // @version 1.3.0 // @description 1.自动播放下一集 2.收藏功能 3.历史观看记录 4.去广告 5.播放记录 6.小窗口播放 7.下载视频 // @author hero-king // @match https://ddrk.me/* // @icon https://ddrk.me/favicon-32x32.png // @run-at document-start // @grant unsafeWindow // @grant GM_listValues // @grant GM_setValue // @grant GM_getValue // @require http://code.jquery.com/jquery-3.3.1.min.js // @require https://cdn.staticfile.org/vue/3.2.33/vue.global.min.js // @require https://cdn.staticfile.org/popper.js/2.11.5/umd/popper.min.js // ==/UserScript== (async function () { "use strict"; // @require https://unpkg.com/@popperjs/core@2 // @require https://unpkg.com/popper.js // @require https://unpkg.com/[email protected]/eruda.js // eruda.init(); const STORE_COLLECTION_KEY = "ddrk-tools-collection"; const STORE_HITORY_KEY = "ddrk-tools-history"; const STORE_RESUME_KEY = "ddrk-tools-resume"; const STORE_SETTINGS_KEY = "ddrk-tools-settings"; const STORE_RECORD_KEY = "ddrk-tools-play-record"; const TIME_END = 215999; //单位:秒(s),59:59:59 const WD = window.unsafeWindow || document.defaultView || window; WD.Vue = Vue; WD.Popper = Popper; /** 广告隐藏class */ const adClass = `<style> .cfa_popup { height: 0 !important; } #iaujwnefhw,#kasjbgih { height: 0 !important; overflow: hidden !important; } <style>`; $("head").append(adClass); /** 页面class */ const mainCss = `<style> .ddrk-tools__modal { position: absolute; left: 0; top: 0; right: 0; bottom: 0; text-align: right; } .dt-icon-loading{ animation: goCircel 1s linear infinite; } @keyframes goCircel{ 0%{ transform: rotate(0deg); } 100%{ transform: rotate(360deg); } } .btn_col-default { position: absolute; top:0; right: -32px; width: 32px; padding: 6px; background-color: rgba(0,0,0,0.6); box-shadow: 4px 0px 8px rgba(0,0,0,0.4); line-height: 1; user-select:none; } .btn_col-playpage { position: fixed; left: 20px; bottom: 70px; display: flex; justify-content: center; align-items: center; width: 42px; height: 42px; z-index: 9999; border-radius: 5%; background: rgba(0,0,0,0.5); cursor: pointer; } .btn_download { position: absolute; right: 0; top: 0; display: flex; justify-content: center; align-items: center; cursor: pointer; z-index: 1; } .col_list { position: fixed; top: 35px; right: 0; width: 0; height: auto; min-height: 54px; box-sizing: border-box; background: #2c2c2c; box-shadow: -20px 10px 60px rgba(0, 0, 0, 0.6); z-index: 999; transition: width .6s; } .col_list:hover { width: 300px; } .col_list:hover .col_list-ul{ overflow: auto; } .col_list .col_list_arrow{ position: absolute; left: -26px; top: 0; width: 26px; padding: 4px; background: #008080; color: #000; border-top-left-radius: 8px; border-bottom-left-radius: 8px; } .col_list > h6{ color: #aaa; margin: 10px 0 5px 0; text-align: center; white-space: nowrap; } .col_list-ul::-webkit-scrollbar { width: 5px; height: 5px } .col_list-ul::-webkit-scrollbar-thumb { border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; background-color: #999; } .col_list-ul::-webkit-scrollbar-track { background-color: transparent } .col_list-ul { width: 300px; height: 300px; padding: 5px 0; overflow: hidden; color: #20B2AA; } .col_list-ul .col_item { display: flex; justify-content: space-between; align-items: center; margin: 5px 0; padding: 0 5px; line-height: 25px; border: 1px solid transparent; border-left: none; border-right: none; } .col_list-ul .col_item a { color: #20B2AA; } .col_list-ul .col_item .col_item-left{ vertical-align: middle; } .col_list-ul .col_item .col_item-left svg{ vertical-align: text-top; } .col_list-ul .col_item .col_item-left .col_item-tags{ display: inline-block; min-width: 23px; text-align: right; padding-right: 4px; box-sizing: content-box; } .col_list-ul .col_item .col_item-right{ display: flex; align-items: center; } .col_list-ul .col_item .his_time{ font-size: 12px; color: #fff; margin-left: 5px; white-space: nowrap; line-height: 1; } .col_list-ul .col_item .his_time_end{ color: #20B2AA; } .col_list-ul .col_item .icon_del{ display: none; cursor: pointer; } .col_list-ul .col_item .icon_top{ display: none; cursor: pointer; } .col_list-ul .col_item:hover { // box-shadow: 0 0 5px rgba(32,178,170,0.2); // border-color: rgba(225,255,255,0.4); background: #333; } .col_list-ul .col_item:hover .icon_del{ display: inline-block; } .col_list-ul .col_item:hover .icon_top{ display: inline-block; } .col_list-ul .col_item:hover .icon_top_tag{ display: none; } .col_list-ul .col_item:hover .col_item-index{ display: none; } /** 小窗播放 css */ .ddrk-tools__video-window-small{ position: fixed !important; right: 5px; bottom: 10px; width: 30vw !important; height: 16.875vw !important; padding: 0 !important; z-index: 9; } .ddrk-tools__video-placeholder{ background: #000; } /** popper css */ #msg-box{ background-color: #fff; color: #606266; padding: 12px; border-radius: 4px; font-size: 14px; box-shadow: 0px 0px 20px rgba(0, 0, 0, .35); z-index: 1; } #msg-box .msg-box_wrapper .video-link{ display: inline-block; font-size: 18px; padding: 5px 0px; } #msg-box .msg-box_btns{ text-align: right; padding: 5px 0; } #msg-box .msg-box_btns button{ padding: 5px 12px; border-radius: 4px; color: #409eff; background: #ecf5ff; outline: none; border: none; cursor: pointer; } #msg-box .msg-box_btns button + button{ margin-left: 8px; } #msg-box[data-popper-placement^='top'] > #msg-arrow { bottom: -4px; } #msg-box[data-popper-placement^='bottom'] > #msg-arrow { top: -4px; } #msg-box[data-popper-placement^='left'] > #msg-arrow { right: -4px; } #msg-box[data-popper-placement^='right'] > #msg-arrow { left: -4px; } #msg-arrow, #msg-arrow::before { position: absolute; width: 8px; height: 8px; background: inherit; } #msg-arrow { visibility: hidden; } #msg-arrow::before { visibility: visible; content: ''; transform: rotate(45deg); } <style>`; $("head").append(mainCss); /** pretty-checkbox css */ $("head").append( `<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/pretty-checkbox/3.0.3/pretty-checkbox.min.css" integrity="sha512-kz4Ae66pquz4nVE5ytJyKfPDkQyHSggaDtT1v8oLfOd8bB+ZgZXNLaxex99MNu4fdCsWmi58mhLtfGk5RgfcOw==" crossorigin="anonymous" referrerpolicy="no-referrer" />` ); const Common = { //参数time为休眠时间,单位为毫秒: sleep(time) { return new Promise((resolve) => { setTimeout(resolve, time); }); }, ready() { return new Promise((resolve) => { $(document).ready(function () { resolve(); }); }); }, isMobile() { return /Mobi|Android|iPhone/i.test(navigator.userAgent); }, request({ url, type } = config) { return new Promise((resolve, reject) => { $.ajax({ url, type, success: function (result) { resolve(result); }, error: function (e) { //失败后回调 reject(e); }, }); }); }, }; const Store = { setValue: function (key, value) { // 兼容移动端 window.GM_setValue ? GM_setValue(key, value) : localStorage.setItem(key, value); }, getValue: function (key) { return window.GM_getValue ? GM_getValue(key) || localStorage.getItem(key) : localStorage.getItem(key); }, listValues: function () { return GM_listValues(); }, }; /** * 获取历史记录localStorage */ const LocalHistory = { async getLocalHistory() { const jsonText = Store.getValue("ddrk-history"); let jsonList = []; if (jsonText) { jsonList = JSON.parse(jsonText); } const localData = this.getLocalStorageData(); // console.log(localData); const newhis = localData.filter( (item) => item.key.indexOf("videojs-resume:") === 0 ); const oldhis = JSON.parse(Store.getValue(STORE_RESUME_KEY) || "[]"); // 差集 const minus = newhis.filter( (newItem) => !oldhis.some( (oldItem) => oldItem.key === newItem.key && oldItem.val === newItem.val ) ); // console.log("minus", minus); const minushis = this.formatLocalData(minus); const filterList = this.filterLocalData(minushis); // console.log("filterListMinus", filterList); let res = this.compareLocalData(jsonList, filterList); for (const item of res) { /** category为修复字段,后续删除判断条件 */ if ((!item.name || !item.category) && (item.errorTimes || 0) < 50) { const { name = "", category } = await this.getDramaName(item.url); item.name = name.indexOf("(") > -1 ? name.split("(")[0] : name; item.category = category; if (!name) { // 记录该记录请求失败次数 item.errorTimes = item.errorTimes ? item.errorTimes++ : 1; } } } // 过滤name不存在的 res = res.filter((item) => item.name); Store.setValue("ddrk-history", JSON.stringify(res)); Store.setValue(STORE_HITORY_KEY, JSON.stringify(res)); Store.setValue(STORE_RESUME_KEY, JSON.stringify(newhis)); return res; }, getLocalStorageData: function () { var len = localStorage.length; // 获取长度 var arr = new Array(); // 定义数据集 for (var i = 0; i < len; i++) { // 获取key 索引从0开始 var getKey = localStorage.key(i); // 获取key对应的值 var getVal = localStorage.getItem(getKey); // 放进数组 arr[i] = { key: getKey, val: getVal, }; } return arr; }, // 格式化 formatLocalData(local) { const history = local.map((item) => { const info = item.key.split("/"); return { ...item, url: item.key.split(":")[1], enName: info[1], season: info.length > 3 && !isNaN(info[2]) ? info[2] : "", ep: info.at(-1).replace("?ep=", ""), t: Date.now(), }; }); return history; }, // 去重 并取最大ep filterLocalData(params) { const result = params.reduce((res, cur) => { const innerItem = res.find( (item) => item.enName === cur.enName && item.season === cur.season ); if (innerItem) { if (+cur.ep > +innerItem.ep) { res.splice( res.findIndex( (item) => item.enName === cur.enName && item.season === cur.season ), 1, cur ); } return res; } else { return res.concat(cur); } }, []); return result; }, // 对比 compareLocalData(myList, updateList) { const unTopIndex = myList.findIndex((ele) => !ele.isTop); // 差集(优先) const difference = []; updateList.forEach((updateItem) => { const index = myList.findIndex( (item) => item.enName === updateItem.enName && item.season === updateItem.season ); if (index !== -1) { const tempItem = { ...myList[index], ...updateItem, }; if (myList[index].isTop) { myList.splice(index, 1, tempItem); // 替换 } else { myList.splice(index, 1); // 删除 myList.splice(unTopIndex, 0, tempItem); // 新增 } } else { difference.push(updateItem); } }); // 插入差集 myList.splice(unTopIndex, 0, difference); return [].concat.apply([], myList); }, async getDramaName(url) { try { const result = await Common.request({ url: `https://ddrk.me${url}`, type: "get", }); //成功后回调 const $result = $(result); const name = $result.find(".post-title").text(); const types = []; $result .find(".meta_categories .cat-links a") .text(function (index, oldcontent) { types.push(oldcontent); }); return { name, category: types.join(",") }; } catch (error) { return {}; } }, }; /** 设置 */ const Settings = { defaultData: [ { id: 1, name: "自动播放下一集", val: true }, { id: 2, name: "点击海报打开新标签", val: true }, { id: 3, name: "播放时提示上次观看位置", val: true }, { id: 4, name: "开启小窗口播放(脱离可视区域时)", val: true }, { id: 5, name: "点击下载直接跳转不再弹框", val: false }, ], getData() { const localDataStr = Store.getValue(STORE_SETTINGS_KEY); if (localDataStr) { const localData = JSON.parse(localDataStr); return this.defaultData.map((item) => { const localItem = localData.find((ele) => ele.id === item.id); if (localItem) { return { ...item, val: localItem.val, }; } else { return item; } }); } return this.defaultData; }, getValueById(id) { return ( settingsList.value.find((item) => item.id === id) || { val: false } ).val; }, }; // 等待页面加载完成 await Common.ready(); // vue容器 $("body").append($(`<div id="ddrk-tools" ></div>`)); const { createApp, toRefs, ref, h, defineComponent, watch } = Vue; const IconCollection = defineComponent({ template: `<svg class="col_list_arrow" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="32" height="32"><path d="M856.8 82.8H386.1c-40.4-43.2-135.5-67-188.9-67-94.9 0-175.8 70.5-188.9 164.4-5.6 16-8.3 31.3-8.3 46.7v603.7c0 98.7 80.3 179.2 179.2 179.2h695.7c82 0 148.8-66.7 148.8-148.8V249.8c0-92.2-74.8-167-166.9-167z m0 30.4c60 0 110.5 39.2 128.7 93.2H627.2l-183.5-93.2h413.1z m136.6 747.7c0 65.3-53.1 118.4-118.4 118.4H179.3c-82 0.1-148.9-66.7-148.9-148.8V226.8c0-12.3 2.3-24.7 7-38l0.8-3.2c10.5-79.4 78.7-139.5 159.1-139.5 56.2 0 142.9 26.7 170.1 61.2l4.6 5.8h2.6l242.3 120.3h374.9c0.6 5.3 1.6 10.6 1.6 16.1v611.4z m0 0" fill="#000000" p-id="2983"></path><path d="M201.3 842.6h791v27.8h-791v-27.8z m-92.9 0h30.3v30.3h-30.3v-30.3z m258-260L346.1 693.8c-1.9 10.7 2.3 21.3 11 27.8 8.8 6.5 20.1 7.4 29.8 2.5l98.7-51.6 99.5 53.6c4.3 2.3 8.9 3.4 13.5 3.4 5.7 0 11.5-1.8 16.4-5.3 8.8-6.3 13.3-16.8 11.6-27.6L608.1 586.8l81.8-78c7.8-7.5 10.7-18.6 7.5-29-3.3-10.4-12-17.8-22.7-19.5L564.5 444l-49-101.9c-4.7-9.8-14.4-15.9-25.2-16.1-9.7-0.5-20.7 5.8-25.6 15.5L415.1 441.1l-112 15.1c-10.7 1.5-19.6 8.8-23.1 19.1s-0.8 21.4 6.9 29.1l79.5 78.2z m52.8-111.3c9.2-1.2 17.2-6.9 21.5-15.3l49.2-97.2 47.2 98.3c4.1 8.4 12 14.3 21.2 15.7L666.1 489.6l-78.8 75.2c-6.7 6.4-9.9 15.7-8.4 25l18.5 108.3-97.3-52.3c-4.2-2.3-8.8-3.4-13.4-3.4-4.4 0-8.9 1-13 3.1l-97 49.7 19.6-107.3c1.7-9.2-1.3-18.6-7.9-25.1l-77.3-77 108.1-14.5z m0 0" fill="#000000" p-id="2984"></path></svg>`, }); const IconHistory = defineComponent({ template: `<svg class="col_list_arrow" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="32" height="32"><path d="M204.8 552.96h204.8a20.48 20.48 0 0 1 0 40.96H204.8a20.48 20.48 0 0 1 0-40.96z" p-id="4654" fill="#000000"></path><path d="M143.36 921.6a40.96 40.96 0 0 1-40.96-40.96V143.36a40.96 40.96 0 0 1 40.96-40.96h614.4a40.96 40.96 0 0 1 40.96 40.96v327.68h40.96V143.36a81.92 81.92 0 0 0-81.92-81.92H143.36a81.92 81.92 0 0 0-81.92 81.92v737.28a81.92 81.92 0 0 0 81.92 81.92h327.68v-40.96z" p-id="4655" fill="#000000"></path><path d="M737.28 512a225.28 225.28 0 1 0 225.28 225.28 225.28 225.28 0 0 0-225.28-225.28z m0 409.6a184.32 184.32 0 1 1 184.32-184.32 184.32 184.32 0 0 1-184.32 184.32z" p-id="4656" fill="#000000"></path><path d="M771.2768 660.6848Q634.88 584.0896 634.88 737.28t136.6016 76.5952q136.192-76.5952-0.2048-153.1904z m-13.5168 122.88Q675.84 829.44 675.84 737.28t81.92-46.08q81.92 46.08 0 92.16zM225.28 307.2h-20.48a20.48 20.48 0 0 0 0 40.96h20.48zM696.32 307.2H266.24v40.96h430.08a20.48 20.48 0 0 0 0-40.96z" p-id="4657" fill="#000000"></path></svg>`, }); const IconSettings = defineComponent({ template: `<svg class="col_list_arrow" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="32" height="32"><path d="M746.666667 469.333333H277.333333C159.509333 469.333333 64 373.824 64 256S159.509333 42.666667 277.333333 42.666667h469.333334c117.802667 0 213.333333 95.509333 213.333333 213.333333s-95.530667 213.333333-213.333333 213.333333z m0-384H277.333333a170.666667 170.666667 0 0 0 0 341.333334h469.333334a170.666667 170.666667 0 0 0 0-341.333334zM277.333333 384a128 128 0 1 1 0-256 128 128 0 0 1 0 256z m0-213.333333a85.333333 85.333333 0 1 0 0 170.666666 85.333333 85.333333 0 0 0 0-170.666666z m0 384h469.333334c117.802667 0 213.333333 95.530667 213.333333 213.333333s-95.530667 213.333333-213.333333 213.333333H277.333333C159.509333 981.333333 64 885.802667 64 768s95.509333-213.333333 213.333333-213.333333z m0 384h469.333334a170.666667 170.666667 0 0 0 0-341.333334H277.333333a170.666667 170.666667 0 0 0 0 341.333334z m469.333334-298.666667a128 128 0 0 1 0 256 128 128 0 0 1 0-256z m0 213.333333a85.333333 85.333333 0 1 0 0-170.666666 85.333333 85.333333 0 0 0 0 170.666666z" fill="#2c2c2c" p-id="12986"></path></svg>`, }); const IconDelete = defineComponent({ template: `<svg class="icon_del" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><title>删除</title><path d="M202.666667 256h-42.666667a32 32 0 0 1 0-64h704a32 32 0 0 1 0 64H266.666667v565.333333a53.333333 53.333333 0 0 0 53.333333 53.333334h384a53.333333 53.333333 0 0 0 53.333333-53.333334V352a32 32 0 0 1 64 0v469.333333c0 64.8-52.533333 117.333333-117.333333 117.333334H320c-64.8 0-117.333333-52.533333-117.333333-117.333334V256z m224-106.666667a32 32 0 0 1 0-64h170.666666a32 32 0 0 1 0 64H426.666667z m-32 288a32 32 0 0 1 64 0v256a32 32 0 0 1-64 0V437.333333z m170.666666 0a32 32 0 0 1 64 0v256a32 32 0 0 1-64 0V437.333333z" p-id="2817" fill="#ffffff"></path></svg>`, }); const IconTop = defineComponent({ template: `<svg class="icon_top" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><title>置顶</title><path d="M555.818667 940.629333c-6.229333 56.746667-85.418667 51.669333-88.533334 0V324.693333l-272.64 263.210667c-42.752 36.778667-93.610667-22.058667-61.824-60.757333 120.704-117.034667 337.322667-326.485333 342.4-331.349334 19.968-21.674667 51.413333-22.784 72.661334 0 39.808 38.442667 334.890667 322.986667 343.808 333.226667 29.952 37.205333-18.432 92.245333-59.733334 61.226667-10.666667-9.002667-276.053333-265.514667-276.053333-265.514667l-0.085333 615.893333zM168.448 42.666667h687.104c14.336 0 21.504 8.704 21.504 26.069333 0 17.408-7.168 26.069333-21.504 26.069333H168.448c-14.336 0-21.504-8.661333-21.504-26.026666 0-17.408 7.168-26.112 21.504-26.112z" p-id="891" fill="#ffffff"></path></svg>`, }); const IconTopCancel = defineComponent({ template: `<svg class="icon_top" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><title>取消置顶</title><path d="M189.3 115h653.4c12.1 0 22-9.9 22-22v-6c0-12.1-9.9-22-22-22H189.3c-12.1 0-22 9.9-22 22v6c0 12.1 9.9 22 22 22zM152.2 524.5c-16.1 15.5-16.5 41.4-1 57.5s41.4 16.5 57.5 1l150.5-145-57.4-57.6-149.6 144.1zM474.5 918.4c0 22.4 18.3 40.6 40.6 40.6 22.4 0 40.6-18.3 40.6-40.6V635.3l-81.3-81.6v364.7zM872.3 524.5L547.1 211.3c-7.5-9.5-19-15.6-32-15.6h-0.5c-0.8 0-1.6 0-2.4 0.1-10.9-0.6-22 3.2-30.4 11.3l-98.4 94.7 57.4 57.6 33.6-32.3v66l81.3 81.6V332.5l260.1 250.4c16.1 15.5 41.9 15.1 57.5-1 15.6-16 15.1-41.9-1-57.4zM257.1 207c-6.6-6.7-15.4-10-24.1-10-8.7 0-17.4 3.3-24 9.9-13.3 13.3-13.3 34.8-0.1 48.1l538 540c6.6 6.7 15.4 10 24.1 10 8.7 0 17.4-3.3 24-9.9 13.3-13.3 13.3-34.8 0.1-48.1l-538-540z" p-id="18070" fill="#ffffff"></path></svg>`, }); const IconTopTag = defineComponent({ template: `<svg class="icon_top_tag" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path d="M320.32 704.18c14.058 14.06 14.058 36.854 0 50.913L125.864 949.547c-14.06 14.059-36.853 14.059-50.912 0-14.059-14.059-14.059-36.853 0-50.912l194.454-194.454c14.06-14.059 36.853-14.059 50.912 0z m629.906-396.904c14.818 14.818 13.897 39.112-2 52.766L717.082 558.556l0.667 2.734c27.425 114.91-4.257 237.542-87.885 325.02l-2.745 2.84-2.725 2.759c-14.036 14.195-36.941 14.26-51.057 0.144L126.447 445.162c-14.06-14.059-14.06-36.853 0-50.912 90.247-90.248 220.23-123.274 340.164-91.125l2.991 0.82 195.22-227.306c13.517-15.74 37.463-16.8 52.322-2.445z m-78.374 23.45L694.138 153.011 508.752 368.87a36 36 0 0 1-38.937 10.616l-3.106-1.086c-88.26-30.386-185.781-14.902-260.063 41.255l-2.2 1.682 392.717 392.718 0.874-1.132c54.977-71.991 71.575-166.167 44.804-252.737l-1.07-3.393a36 36 0 0 1 10.96-37.877l219.12-188.19z" p-id="15602" fill="#FA8D14"></path></svg>`, }); // 收藏组件 const ComponentCollection = { setup(props, { slots }) { return () => h( "ul", { class: "col_list-ul", }, colList.value.map((item, index) => { return h( "li", { class: "col_item", onClick: () => { // window.location.href = item.href; }, }, [ h("span", [ `${index + 1}. `, h("a", { href: item.href }, `${item.name}`), ]), h(IconDelete, { class: "icon_del", onClick: (event) => { event.stopPropagation(); LocalCollection.handleColDel(index); LocalCollection.reloadCollectButton(); }, }), ] ); }) ); }, }; // 历史组件 const ComponentHistory = { setup(props, { slots }) { watch( hisList, (newVal, oldVal) => { Store.setValue("ddrk-history", JSON.stringify(newVal)); Store.setValue(STORE_HITORY_KEY, JSON.stringify(newVal)); }, { deep: true } ); const cancelTop = (item) => { if (!item.isTop) return; item.isTop = false; const newItem = hisList.value.splice( hisList.value.findIndex((ele) => ele.key === item.key), 1 )[0]; const unTopIndex = hisList.value.findIndex((ele) => !ele.isTop); hisList.value.splice(unTopIndex, 0, newItem); }; const handleTop = (item) => { item.isTop = true; hisList.value.unshift( hisList.value.splice( hisList.value.findIndex((ele) => ele.key === item.key), 1 )[0] ); }; const formatTime = (time) => { const hour = parseInt(time / 3600) > 0 ? parseInt(time / 3600) : 0; const min = parseInt((time - hour * 3600) / 60) > 0 ? parseInt((time - hour * 3600) / 60) : 0; const sec = parseInt(time - hour * 3600 - min * 60); const resultStr = `${hour > 9 ? hour : "0" + hour}:${ min > 9 ? min : "0" + min }:${sec > 9 ? sec : "0" + sec}`; return resultStr; }; return () => h( "ul", { class: "col_list-ul", }, hisList.value .filter((item) => { // 对比集数有没有变化 // 没有变化就对比观看时间有没有变化 return item.deleteInfo ? item.ep !== item.deleteInfo.ep ? true : item.ep === item.deleteInfo.ep && item.val !== item.deleteInfo.val : true; }) .map((item, index) => { const season = item.season ? `S${item.season}` : ""; const ep = item.category?.includes("电影") ? "" : item.ep ? `E${item.ep}` : ""; const timeStr = +item.val === TIME_END ? "已看完" : +item.val === 0 ? "未观看" : formatTime(item.val); return h( "li", { class: "col_item", onClick: () => { // window.location.href = item.url; }, }, [ h("span", { class: "col_item-left" }, [ h("span", { class: "col_item-tags" }, [ item.isTop ? h(IconTopCancel, { onClick: () => cancelTop(item), }) : h(IconTop, { onClick: () => handleTop(item), }), item.isTop ? h(IconTopTag) : h( "span", { class: "col_item-index" }, `${ index + 1 - hisList.value.filter((ele) => ele.isTop).length }.` ), ]), h("a", { href: item.url }, `${item.name} ${season}${ep}`), ]), h( "div", { class: "col_item-right", }, [ h(IconDelete, { onClick: () => { // 删除时记录下当前值,后续进行对比 item.deleteInfo = { ep: item.ep, val: item.val, t: Date.now(), }; cancelTop(item); }, }), h( "span", { class: { his_time: true, his_time_end: +item.val === TIME_END, }, }, timeStr ), ] ), ] ); }) ); }, }; // 设置组件 const ComponentSettings = { setup(props, { slots }) { return () => h( "ul", { class: "col_list-ul", }, settingsList.value.map((item, index) => { return h( "li", { class: "col_item", }, [ h("span", item.name), h( "div", { class: "pretty p-switch p-fill", }, [ h("input", { type: "checkbox", checked: !!item.val, onChange: (e) => { item.val = e.target.checked; Store.setValue( STORE_SETTINGS_KEY, JSON.stringify(settingsList.value) ); }, }), h("div", { class: "state p-primary" }, h("label")), ] ), ] ); }) ); }, }; // 外壳组件 const ListBody = { props: { title: { type: String, required: true, }, style: { type: Object, required: true, }, }, setup(props, { slots }) { const { title, style } = toRefs(props); const iconArr = { 收藏夹: [IconCollection, ComponentCollection], 观看记录: [IconHistory, ComponentHistory], 设置: [IconSettings, ComponentSettings], }; return () => h("div", { class: "col_list", style: style?.value }, [ h("h6", title.value), h(iconArr[title.value][0]), h(iconArr[title.value][1]), ]); }, }; let colList = ref(JSON.parse(Store.getValue("ddrk-collection") || "[]")); let hisList = ref(await LocalHistory.getLocalHistory()); let settingsList = ref(Settings.getData()); // 根组件 const ComponentApp = { render() { return h("div", { class: "ddrk-tools-container" }, [ h(ListBody, { title: "收藏夹", style: { top: "35px", "z-index": 100 }, }), h(ListBody, { title: "观看记录", style: { top: "85px", "z-index": 99 }, }), h(ListBody, { title: "设置", style: { top: "135px", "z-index": 98 }, }), ]); }, }; const app = createApp(ComponentApp); app.mount("#ddrk-tools"); const MessageBox = { init() { $("body").append( $( `<div id="msg-box"> <div class="msg-box_wrapper"> </div> <div id="msg-arrow" data-popper-arrow></div> </div>` ) ); }, $popover({ target, html, timeout = 8000 } = config) { $("#msg-box .msg-box_wrapper").html(html); const popover = new Popper.createPopper(target, $("#msg-box")[0], { placement: "top", modifiers: [ { name: "offset", options: { offset: [0, 10], }, }, { name: "flip", options: { fallbackPlacements: ["top", "bottom"], }, }, ], }); setTimeout(() => { popover.destroy(); }, timeout); }, $confirm({ target, html, confirmText = "确定", cancelText = "取消", showConfirm = true, showCancel = true, confirmCallBack, cancelCallBack, } = config) { const btns = `<div class="msg-box_btns"> ${ showConfirm ? `<button class="msg-box_btn-confirm">${confirmText}</button>` : "" } ${ showCancel ? `<button class="msg-box_btn-cancle">${cancelText}</button>` : "" } </div>`; $("#msg-box .msg-box_wrapper").html(html + btns); const popover = new Popper.createPopper(target, $("#msg-box")[0], { placement: "top", modifiers: [ { name: "offset", options: { offset: [0, 10], }, }, { name: "flip", options: { fallbackPlacements: ["top", "bottom"], }, }, ], }); $("#msg-box .msg-box_wrapper").on( "click", ".msg-box_btn-confirm", (e) => { confirmCallBack?.(popover); } ); $("#msg-box .msg-box_wrapper").on("click", ".msg-box_btn-cancle", (e) => { popover.destroy(); cancelCallBack?.(); }); }, }; MessageBox.init(); // 监听 页面显示隐藏 document.addEventListener("visibilitychange", async function () { // console.log("-----------", document.visibilityState); if (document.visibilityState == "hidden") { //切离该页面时执行 // 标签隐藏时自动暂停播放(后续开发) } else if (document.visibilityState == "visible") { //切换到该页面时执行 // 刷新历史记录-因为需要和localStorage对比 settingsList.value = Settings.getData(); colList.value = JSON.parse(Store.getValue("ddrk-collection") || "[]"); LocalCollection.reloadCollectButton(); hisList.value = await LocalHistory.getLocalHistory(); } }); /** * 蒙层及收藏 */ const IconStarSlim = '<svg viewBox="0 0 1026 1024" xmlns="http://www.w3.org/2000/svg" width="20" height="20"><title>收藏</title><path d="M1019.109859 384c-11.286261-32.01113-39.713391-55.05113-74.195478-60.126609L701.69212 288.233739l-105.627826-216.019478c-15.270957-31.276522-48.261565-51.489391-84.057043-51.489391-35.706435 0-68.652522 20.21287-83.968 51.489391l-105.672348 216.041739L79.166902 323.940174c-34.504348 4.964174-62.953739 27.981913-74.24 60.17113-11.264 32.50087-2.871652 67.806609 21.882435 92.137739l178.509913 175.638261-41.405217 243.378087c-5.810087 33.925565 9.282783 68.719304 38.555826 88.687304 28.627478 19.255652 67.005217 21.370435 97.836522 5.164522l211.745391-112.39513 211.878957 112.417391c13.712696 7.234783 29.094957 11.063652 44.521739 11.063652 19.010783 0 37.420522-5.609739 53.337043-16.317217 29.139478-19.878957 44.210087-54.650435 38.4-88.576l-41.382957-243.400348 178.532174-175.638261C1022.048294 451.917913 1030.440641 416.589913 1019.109859 384zM966.062207 444.527304l-195.094261 191.955478 45.278609 266.329043c2.938435 17.096348-4.585739 34.05913-19.478261 44.232348-15.248696 10.24-35.817739 11.330783-52.045913 2.782609L512.00725 826.323478l-232.537043 123.436522c-16.406261 8.637217-36.997565 7.479652-52.045913-2.671304-15.048348-10.262261-22.572522-27.247304-19.634087-44.343652l45.30087-266.284522-195.072-191.955478c-12.377043-12.154435-16.606609-29.718261-11.063652-45.723826 5.765565-16.384 20.524522-28.182261 38.622609-30.786783l266.48487-39.112348 115.97913-237.122783c7.880348-16.11687 25.154783-26.534957 43.987478-26.534957 18.899478 0 36.173913 10.395826 44.054261 26.512696l115.95687 237.122783 266.418087 39.023304c18.075826 2.671304 32.901565 14.514087 38.64487 30.809043C982.668815 414.786783 978.43925 432.328348 966.062207 444.527304zM509.046555 376.898783c-45.590261 0-82.320696 13.913043-109.122783 41.316174-44.744348 45.746087-43.78713 112.194783-43.720348 115.021913 0.26713 12.109913 10.173217 21.726609 22.238609 21.726609 0.133565 0 0.289391 0 0.422957 0 12.265739-0.222609 22.016-10.373565 21.837913-22.639304 0-0.512-0.400696-51.066435 31.254261-83.18887 18.098087-18.387478 44.054261-27.692522 77.06713-27.692522 12.288 0 22.26087-9.97287 22.26087-22.26087S521.334555 376.898783 509.046555 376.898783z" p-id="6346" fill="#008080"></path></svg>'; const IconStarFill = '<svg viewBox="0 0 1071 1024" xmlns="http://www.w3.org/2000/svg" width="20" height="20"><title>已收藏</title><path d="M595.741436 18.32575a97.371215 97.371215 0 0 1 23.150006 23.563834l135.589417 195.61877a48.685607 48.685607 0 0 0 27.823824 19.401215l214.411416 55.47725a97.371215 97.371215 0 0 1 54.138395 151.850409l-143.69557 195.910885a48.685607 48.685607 0 0 0-9.420665 29.381764l2.677708 216.504896a97.371215 97.371215 0 0 1-126.533894 94.109279l-219.133919-68.817106a48.685607 48.685607 0 0 0-28.821879-0.121714l-231.402693 70.740188a97.371215 97.371215 0 0 1-125.852295-93.111224v-220.78923a48.685607 48.685607 0 0 0-8.203525-27.069198L26.801427 461.194378a97.371215 97.371215 0 0 1 55.574621-148.150304l208.301371-56.158848a48.685607 48.685607 0 0 0 26.82577-18.573559l142.332373-197.809623a97.371215 97.371215 0 0 1 135.905874-22.176294z m104.1872 535.298254c-37.926088 42.940706-89.16769 64.265002-157.49794 64.265001-68.963163 0-123.564072-21.859838-166.821234-66.090712a48.685607 48.685607 0 0 0-69.620419 68.062479c62.025464 63.437347 141.845517 95.423791 236.465995 95.423791 95.277734 0 173.320763-32.521986 230.453323-97.249501a48.685607 48.685607 0 0 0-73.004068-64.411058z" p-id="2830" fill="#008080"></path></svg>'; const LocalCollection = { playPageHref: "", init() { const modal = $( `<a class='ddrk-tools__modal' title='ddrk助手功能: 点击打开新标签(可取消)'></a>` ); if ($(".post-box").length) { $(".post-box").each(function () { modal.attr("href", $(this).data("href")); $(this).append(modal.clone(true)); }); } else { this.playPageHref = window.location.origin + "/" + window.location.pathname.split("/")[1] + "/"; } this.reloadCollectButton(); this.bindEvent(); }, bindEvent() { const self = this; // 点击打开新页签 $(".post-box").on("click", ".ddrk-tools__modal", function (e) { console.log("opentab: ", Settings.getValueById(2)); if (Settings.getValueById(2)) { window.open($(this).parent().data("href")); } else { window.location.href = $(this).parent().data("href"); } e.stopPropagation(); return false; // 阻止a标签默认行为 }); $(".post-box").on("click", ".btn_col-default", function (e) { e.stopPropagation(); }); $(".post-box").on("click", ".btn_col-add", function (e) { const href = $(this).parent().data("href"); const name = $(this).parent().find(".post-box-title a").text(); if (!colList.value.find((item) => item.href === href)) { colList.value.push({ name: name.indexOf("(") > -1 ? name.split("(")[0] : name, href, }); /** 一个月后常量替换该字段, 当前版本0.5 */ Store.setValue("ddrk-collection", JSON.stringify(colList.value)); Store.setValue(STORE_COLLECTION_KEY, JSON.stringify(colList.value)); } self.toggleButton($(this), 1); }); $(".post-box").on("click", ".btn_col-remove", function (e) { const href = $(this).parent().data("href"); const index = colList.value.findIndex((item) => item.href === href); self.handleColDel(index); self.toggleButton($(this), 0); }); // 播放页点击 $("#ddrk-tools").on("click", ".btn_col-remove", function (e) { const index = colList.value.findIndex( (item) => item.href === self.playPageHref ); self.handleColDel(index); self.toggleButton($(this), 0); }); $("#ddrk-tools").on("click", ".btn_col-add", function (e) { const name = $(".post-title").text(); if (!colList.value.find((item) => item.href === self.playPageHref)) { colList.value.push({ name: name.indexOf("(") > -1 ? name.split("(")[0] : name, href: self.playPageHref, }); /** 一个月后常量替换该字段, 当前版本0.5 */ Store.setValue("ddrk-collection", JSON.stringify(colList.value)); Store.setValue(STORE_COLLECTION_KEY, JSON.stringify(colList.value)); } self.toggleButton($(this), 1); }); }, toggleButton(tempBtn, tag) { if (tag === 0) { tempBtn.addClass("btn_col-add"); tempBtn.removeClass("btn_col-remove"); tempBtn.html(IconStarSlim); } else { tempBtn.addClass("btn_col-remove"); tempBtn.removeClass("btn_col-add"); tempBtn.html(IconStarFill); } }, // 刷新页面收藏按钮 reloadCollectButton() { const self = this; if ($(".post-box").length) { $(".post-box").each(function () { let tempBtn = $(this).find(".btn_col-default"); if (!tempBtn.length) { tempBtn = $( `<span class="btn_col-default btn_col-remove">${IconStarFill}</span>` ); $(this).append(tempBtn); } if ( !colList.value.find((item) => item.href === $(this).data("href")) ) { self.toggleButton(tempBtn, 0); } else { self.toggleButton(tempBtn, 1); } }); } else { let tempBtn = $(".btn_col-playpage"); if (!tempBtn.length) { tempBtn = $( `<span class="btn_col-playpage btn_col-remove">${IconStarFill}</span>` ); $("#ddrk-tools").append(tempBtn); } if (!colList.value.find((item) => item.href === this.playPageHref)) { self.toggleButton(tempBtn, 0); } else { self.toggleButton(tempBtn, 1); } } }, // 删除已收藏 handleColDel(index) { if (index !== -1) { colList.value.splice(index, 1); Store.setValue("ddrk-collection", JSON.stringify(colList.value)); Store.setValue(STORE_COLLECTION_KEY, JSON.stringify(colList.value)); } }, }; LocalCollection.init(); await Common.sleep(50); // 等待video初始化 /** * 自动跳转并播放下一集 */ const autoPlayNext = { player: null, playerModel: {}, nextType: "hand", // 手动 | 自动 init() { this.initPlayer(); this.bindEvent(); }, initPlayer() { this.player = WD.videojs?.getAllPlayers()[0]; console.time("视频源数据加载完成"); // 监听 this.player?.one("canplaythrough", async (e) => { console.timeEnd("视频源数据加载完成"); await Common.sleep(200); this.nextType === "auto" && this.restoreVideoModel(); }); this.player?.on("ended", async () => { console.log("ended"); console.log("autonext:", Settings.getValueById(1)); console.log("lastEp:", this.isLastEP()); if (!Settings.getValueById(1)) return; if (this.isLastEP()) return this.setResume(TIME_END); this.getCurrentVideoModel(); // 在下一集之前获取当前video状态 this.handleToNext(); this.nextType = "auto"; await Common.sleep(200); this.initPlayer(); this.handleToPlay(); }); }, bindEvent() { // 主动点击下一集 $(WD.document).on( "click", ".wp-playlist-tracks .wp-playlist-item, icon-angle-right", async (e) => { await Common.sleep(200); this.initPlayer(); this.nextType = "hand"; } ); }, getCurrentVideoModel() { // 保存当前video模式 this.playerModel = { isFullscreen: this.player.isFullscreen_, // 全屏 isInPictureInPicture: !!document.pictureInPictureElement, // 画中画 isFullWindow: !!$(".vjs-theater-mode-control-close").length, // 网页全屏:打开时会包含vjs-theater-mode-control-close }; }, handleToNext() { (this.player.controlBar.childNameIndex_.nextButton || {}).handleClick(); // 下一集按钮 }, handleToPlay() { if (this.player.resumeModal?.opened_) { // 已打开恢复弹框则选择 是 this.player.resumeModal.childNameIndex_.modalButtons.childNameIndex_.resumeButton.el_.click(); } else { this.player.bigPlayButton?.el_.click(); //播放按钮 this.setResume(0); } }, async restoreVideoModel() { // 恢复上次video模式 if (this.playerModel.isFullscreen) { $(".vjs-fullscreen-control").trigger("click"); } else if (this.playerModel.isInPictureInPicture) { $(".vjs-picture-in-picture-control").trigger("click"); } else if (this.playerModel.isFullWindow) { $(".vjs-theater-mode-control-open").trigger("click"); } }, isLastEP() { return $(".wp-playlist-item:last-child").hasClass("wp-playlist-playing"); }, setResume(value = 0) { localStorage.setItem( window.location.href.replace("https://ddrk.me", "videojs-resume:"), value ); }, }; autoPlayNext.init(); /** * 播放页上次观看记录提示 */ const watchRecord = { recordData: {}, init() { // 有播放器则继续 if (WD.videojs?.getAllPlayers()[0]) { this.initPlayer(); this.recordData = this.getRecord(); if (!Settings.getValueById(3)) return; const curPageInfo = this.parseUrl(); const lastInfo = this.recordData[curPageInfo.enName]; // console.log("-curInfo--", curPageInfo); // console.log("-recordData--", this.recordData); if ( lastInfo && (curPageInfo.season !== lastInfo?.season || curPageInfo.ep !== lastInfo?.ep) ) { const season = lastInfo.season ? `S${lastInfo.season} - ` : ""; const ep = lastInfo.ep ? `E${lastInfo.ep}` : ""; MessageBox.$popover({ target: $("#vjsp_html5_api")[0], html: "上次观看到:" + `<a href="${lastInfo.href}">${season}${ep}</a>`, }); } } }, initPlayer() { const player = WD.videojs?.getAllPlayers()[0]; player?.one("canplay", () => this.setRecord()); }, getRecord() { return JSON.parse(Store.getValue(STORE_RECORD_KEY) || "{}"); }, setRecord() { const escData = this.parseUrl(); // 防止电影和只有一季的保存第一集 if (escData.ep > 1 || escData.season >= 1) { this.recordData[escData.enName] = escData; Store.setValue(STORE_RECORD_KEY, JSON.stringify(this.recordData)); } }, parseUrl() { const info = window.location.pathname.split("/"); return { enName: info[1], season: info.length > 3 && !isNaN(info[2]) ? info[2] : $(".post-page-numbers").text() ? "1" : "", ep: new URL(location.href).searchParams.get("ep"), href: window.location.href, }; }, }; watchRecord.init(); /** 小窗播放 */ const PlayInSmallWindow = { player: null, isPlaying: false, offsetTop: 0, eleHeight: 0, init() { // 有播放器则继续 if (WD.videojs?.getAllPlayers()[0]) { this.offsetTop = $(".wp-video-playlist").offset().top; this.eleHeight = $("#vjsp_html5_api").height(); this.initPlayer(); this.bindEvent(); $(".wp-video-playlist").prepend( $(`<div class="ddrk-tools__video-placeholder" ></div>`) ); } }, initPlayer() { this.player = WD.videojs?.getAllPlayers()[0]; this.player?.on("playing", () => { // console.log("视频播放中"); this.isPlaying = true; }); this.player?.on("pause", () => { // console.log("视频暂停播放"); this.isPlaying = false; }); this.player?.on("ended", () => { // console.log("视频播放结束"); this.isPlaying = false; }); }, bindEvent() { $(window).resize(() => { this.offsetTop = $(".wp-video-playlist").offset().top; this.eleHeight = $(".ddrk-tools__video-placeholder").height() || $("#vjsp_html5_api").height(); }); $(window).scroll(() => { if ( !this.isPlaying && !$("#vjsp").hasClass("ddrk-tools__video-window-small") ) { return; } //开始监听滚动条 const target = this.offsetTop + this.eleHeight * 0.8; if ( target >= $(window).scrollTop() && this.offsetTop < $(window).scrollTop() + $(window).height() ) { // console.log("div在可视范围"); $(".ddrk-tools__video-placeholder").css({ width: 0, height: 0, }); $("#vjsp").removeClass("ddrk-tools__video-window-small"); } else if (!$("#vjsp").hasClass("ddrk-tools__video-window-small")) { if (!Settings.getValueById(4)) return; $(".ddrk-tools__video-placeholder").css({ width: "100%", height: $("#vjsp").outerHeight(), }); $("#vjsp").addClass("ddrk-tools__video-window-small"); } }); }, }; PlayInSmallWindow.init(); // 监听路由变化 if (history.replaceState != null) { let _replaceState = history.replaceState; history.replaceState = function () { setTimeout(() => { console.log("-replaceState-"); watchRecord.initPlayer(); PlayInSmallWindow.initPlayer(); Download.bindEvent(); }, 0); return _replaceState.apply(history, arguments); }; } // 视频下载 const IconLoading = `<svg class="dt-icon-loading" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="20" height="20"><path d="M512 64c247.2 0 448 200.8 448 448h-64c0-212-172-384-384-384V64z m0 832c-212 0-384-172-384-384H64c0 247.2 200.8 448 448 448v-64z" p-id="7200" fill="#008080"></path></svg>`; const IconDownload = `<svg class="" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="20" height="20"><path d="M663.466667 701.866667c-17.066667-17.066667-42.666667-17.066667-59.733334 0L554.666667 750.933333V435.2c0-23.466667-19.2-42.666667-42.666667-42.666667s-42.666667 19.2-42.666667 42.666667v313.6l-46.933333-46.933333c-17.066667-17.066667-42.666667-17.066667-59.733333 0s-17.066667 42.666667 0 59.733333l121.6 121.6c6.4 8.533333 17.066667 12.8 27.733333 12.8s21.333333-4.266667 29.866667-12.8l121.6-121.6c17.066667-14.933333 17.066667-42.666667 0-59.733333z" fill="#008080" p-id="14937"></path><path d="M812.8 388.266667C793.6 241.066667 663.466667 128 512 128S230.4 241.066667 211.2 388.266667c-102.4 19.2-179.2 113.066667-172.8 221.866666 6.4 113.066667 106.666667 200.533333 219.733333 200.533334h64c8.533333 0 10.666667-8.533333 6.4-14.933334-32-32-36.266667-85.333333-6.4-119.466666 23.466667-25.6 57.6-34.133333 89.6-25.6 4.266667 2.133333 10.666667-2.133333 10.666667-8.533334v-206.933333c0-49.066667 36.266667-85.333333 89.6-85.333333s89.6 34.133333 89.6 85.333333v206.933333c0 6.4 4.266667 10.666667 10.666667 8.533334 32-8.533333 66.133333 0 89.6 25.6 29.866667 34.133333 25.6 87.466667-6.4 119.466666-6.4 6.4-2.133333 14.933333 6.4 14.933334h64c115.2 0 213.333333-87.466667 219.733333-200.533334 6.4-108.8-70.4-202.666667-172.8-221.866666z" fill="#008080" p-id="14938"></path></svg>`; const Download = { trackList: [], downloadClickable: true, init() { // 有播放器则继续 if (WD.videojs?.getAllPlayers()[0]) { if ($(".wp-playlist-item").length) { $(".wp-playlist-item").each(function () { $(this).append( $(`<span class="btn_download">${IconDownload}</span>`) ); }); } this.bindEvent(); this.trackList = JSON.parse($("script.wp-playlist-script").text() || "{}").tracks || []; } }, bindEvent() { const self = this; $(".wp-playlist-item .btn_download").on("click", async function (e) { e.stopPropagation(); // 节流 if (!self.downloadClickable) return; self.downloadClickable = false; $(this).html(IconLoading); const pageCaption = $(this) .parent() .find(".wp-playlist-caption") .text(); const targetItem = self.trackList.find((item) => pageCaption.includes(item.caption) ); let videoResult = {}; let hasVtt = true; // 判断是否有字幕 const vttUrl = `https://ddrk.me/subddr${targetItem.subsrc}`; try { // 获取视频链接 videoResult = await Common.request({ url: `https://ddrk.me/getvddr/video?id=${targetItem.src1}&type=mix`, type: "get", }); hasVtt = !!(await Common.request({ url: vttUrl, type: "get", })); } catch (error) { console.log(error); hasVtt = false; } finally { self.downloadClickable = true; $(this).html(IconDownload); } const fileName = self.getFileName($(this)); // 直接跳转不弹框 if (Settings.getValueById(5)) { if (!videoResult.url) { MessageBox.$popover({ target: $(this)[0], html: `无法获取视频链接 请重试`, timeout: 1000, }); return; } // 下载视频 const a = document.createElement("a"); a.href = videoResult.url; a.target = "_blank"; a.click(); a.remove(); // 复制文件名到 self.copyToBord(fileName); // 下载字幕 hasVtt && self.downloadVtt(vttUrl, `${fileName}.vtt`); return; } MessageBox.$confirm({ html: videoResult.url ? `<a id="download-video" class="video-link" href="${ videoResult.url }" target="_blank">>视频地址<</a> <br/> ${ hasVtt ? `<a id="download-vtt" class="video-link" href="javascript:void(0)">>点击此处下载字幕<</a>` : "" } <br/> 下载方法:<br/> 1、建议使用IDM、FDM等软件安装其浏览器插件后,点击链接下载<br/> 2、右键链接另存为<br/> 3、右键复制链接 去其它工具下载<br/> ->点击视频地址会自动复制文件名<-<br/> ` : `无法获取视频链接 请重试`, target: $(this)[0], showConfirm: !!videoResult.url, confirmText: "复制文件名", cancelText: "关闭", confirmCallBack: (popper) => { self.copyToBord(fileName); $(".msg-box_btn-confirm").text("复制成功"); }, }); $("#msg-box #download-video").on("mousedown", (e) => { //右击 if (3 == e.which) { self.copyToBord(fileName); } //左击 if (1 == e.which) { self.copyToBord(fileName); } return false; }); $("#msg-box #download-vtt").on("click", (e) => { self.downloadVtt(vttUrl, `${fileName}.vtt`); }); }); }, // 下载字幕 downloadVtt(url, name) { fetch(url) .then((res) => res.arrayBuffer()) .then((arrayBuffer) => { let eAB = arrayBuffer; let wordArray = CryptoJS.lib.WordArray.create(eAB.slice(16)); let hexStr = Array.prototype.map .call(new Uint8Array(eAB.slice(0, 16)), (x) => ("00" + x.toString(16)).slice(-2) ) .join(""); let wordArray2 = CryptoJS.enc.Hex.parse(hexStr); let jsdec = CryptoJS.AES.decrypt( { ciphertext: wordArray }, wordArray2, { iv: wordArray2, mode: CryptoJS.mode.CBC, } ); let binary_string = window.atob(jsdec.toString(CryptoJS.enc.Base64)); let len = binary_string.length; let bytes = new Uint8Array(len); for (let i = 0; i < len; i++) { bytes[i] = binary_string.charCodeAt(i); } let blobStr = pako.ungzip(bytes.buffer, { to: "string" }); blobStr = blobStr.replaceAll("‎", ""); const a = document.createElement("a"); const objectUrl = window.URL.createObjectURL(new Blob([blobStr])); a.download = name; a.href = objectUrl; a.click(); window.URL.revokeObjectURL(objectUrl); a.remove(); }); }, getFileName(element) { const current = $(element).parent(); const name = $(".post-title").text(); const resName = name.indexOf("(") > -1 ? name.split("(")[0] : name; let season = $(".post-page-numbers.current").text(); season = season ? "S" + season : ""; const ep = $(".wp-playlist-item").length === 0 ? "" : "E" + (current.index() + 1); return resName + season + ep; }, copyToBord(text) { let copy = (e) => { e.preventDefault(); e.clipboardData.setData("text/plain", text); document.removeEventListener("copy", copy); }; document.addEventListener("copy", copy); document.execCommand("Copy"); }, }; Download.init(); })();