// ==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();
})();