// ==UserScript==
// @name bilibili favlist backup
// @name:zh-CN 哔哩哔哩(B站|Bilibili)收藏夹Fix (备份视频信息)
// @name:zh-TW 哔哩哔哩(B站|Bilibili)收藏夹Fix (备份视频信息)
// @namespace http://tampermonkey.net/
// @version 16
// @description automatically backup info of videos in favlist
// @description:zh-CN 自动备份视频信息至本地和第三方网站, 失效视频信息回显
// @description:zh-TW 自动备份视频信息至本地和第三方网站, 失效视频信息回显
// @author YTB0710
// @match https://space.bilibili.com/*
// @connect bbdownloader.com
// @connect bilibili.com
// @connect biliplus.com
// @connect jiji.moe
// @connect jijidown.com
// @connect xbeibeix.com
// @grant GM_openInTab
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @grant GM_listValues
// @grant GM_getValues
// @grant GM_xmlhttpRequest
// ==/UserScript==
(function () {
'use strict';
const updates = '更新内容:<br>' +
'新增: 设置获取数据的最小更新间隔的功能';
const version = 16;
const favlistURLRegex = /https:\/\/space\.bilibili\.com\/\d+\/favlist.*/;
const localeTimeStringRegex = /^\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2}$/;
const getFidFromURLRegex = /fid=(\d+)/;
const getFtypeFromURLRegex = /ftype=(\w+)/;
const getUIDFromURLRegex = /https:\/\/space\.bilibili\.com\/(\d+)/;
const getBVFromURLRegex = /video\/(BV\w{10})/;
const getHttpsFromURLRegex = /^https?:\/\//;
const getJsonFromBiliplusRegex = /window\.addEventListener\('DOMContentLoaded',function\(\){view\((.+)\);}\);/;
const getFilenameFromURLRegex = /[^/]+(?:\.[a-zA-Z0-9]+)$/;
const getAvifFromURLRegex = /@.*/;
// let AVBVs;
// let fidOfAVBVs;
let onFavlistPage = false;
let enableAutoNextPage = false;
let enableDebug = false;
let newFreshSpace;
let classAppendNewFreshSpace;
let pageSize;
// let mutations_count = 0;
// let mutation_count = 0;
let firstTimeMain = true;
let divMessage;
let divMessageHeightFixed = false;
let order = 'mtime';
const activeControllers = new Set();
const sortedKeys = [
'BV',
'AV',
'title',
'intro',
'cover',
'upperUID',
'upperName',
'upperAvatar',
'timeUpload',
'timePublish',
'timeFavorite',
'dynamic',
'pages',
'api',
'apiExtra',
'biliplus',
'jijidown',
'jijidownExtra',
'xbeibeix',
// 'preferredTitle',
// 'preferredCover',
];
const settings = GM_getValue('settings', {
version: 0,
processNormal: true,
processDisabled: true,
enableGetFromApi: true,
enableGetFromApiExtra: false,
enableGetFromBiliplus: true,
enableGetFromJijidown: false,
enableGetFromJijidownExtra: false,
enableGetFromXbeibeix: false,
defaultFavlistFid: null,
defaultUID: null,
getFromJijidownURL: 'www.jijidown.com',
getFromXbeibeixURL: 'xbeibeix.com',
displayAdvancedControls: false,
advancedDisableUpdateGetFromApi: false,
advancedDisableUpdateGetFromApiExtra: false,
advancedDisableUpdateGetFromBiliplus: true,
advancedDisableUpdateGetFromJijidown: true,
advancedDisableUpdateGetFromJijidownExtra: true,
advancedDisableUpdateGetFromXbeibeix: true,
advancedIntervalGetFromApi: 5,
advancedIntervalGetFromApiExtra: 5,
advancedIntervalGetFromBiliplus: 10,
advancedIntervalGetFromJijidown: 10,
advancedIntervalGetFromJijidownExtra: 10,
advancedIntervalGetFromXbeibeix: 10,
advancedIntervalAutoNextPage: 5,
});
///////////////////////////////////////////////////////////////////////////////////
// enableDebug = true;
// settings.processNormal = false;
// settings.processDisabled = false;
// settings.enableGetFromApi = false;
// settings.enableGetFromBiliplus = false;
// v9
if (typeof settings.defaultFavlistFid === 'string') {
settings.defaultFavlistFid = parseInt(settings.defaultFavlistFid, 10);
GM_setValue('settings', settings);
}
// v10
if (settings.hasOwnProperty('enableGetFromJiji')) {
settings.enableGetFromJijidown = settings.enableGetFromJiji;
delete settings.enableGetFromJiji;
GM_setValue('settings', settings);
}
// v10
if (settings.hasOwnProperty('enableGetFromBbdownloader')) {
settings.enableGetFromXbeibeix = settings.enableGetFromBbdownloader;
delete settings.enableGetFromBbdownloader;
GM_setValue('settings', settings);
}
// v10
if (!settings.hasOwnProperty('getFromJijidownURL')) {
settings.getFromJijidownURL = 'www.jijidown.com';
GM_setValue('settings', settings);
}
// v10
if (!settings.hasOwnProperty('getFromXbeibeixURL')) {
settings.getFromXbeibeixURL = 'xbeibeix.com';
GM_setValue('settings', settings);
}
// v13
if (settings.hasOwnProperty('enableDebug')) {
delete settings.enableDebug;
GM_setValue('settings', settings);
}
// v14
if (!settings.hasOwnProperty('enableGetFromApiExtra')) {
settings.enableGetFromApiExtra = false;
GM_setValue('settings', settings);
}
// v14
if (!settings.hasOwnProperty('enableGetFromJijidownExtra')) {
settings.enableGetFromJijidownExtra = false;
GM_setValue('settings', settings);
}
// v16
if (!settings.enableGetFromApi && settings.enableGetFromApiExtra) {
settings.enableGetFromApiExtra = false;
GM_setValue('settings', settings);
}
// v16
if (!settings.hasOwnProperty('displayAdvancedControls')) {
settings.displayAdvancedControls = false;
settings.advancedDisableUpdateGetFromApi = false;
settings.advancedDisableUpdateGetFromApiExtra = false;
settings.advancedDisableUpdateGetFromBiliplus = true;
settings.advancedDisableUpdateGetFromJijidown = true;
settings.advancedDisableUpdateGetFromJijidownExtra = true;
settings.advancedDisableUpdateGetFromXbeibeix = true;
settings.advancedIntervalGetFromApi = 5;
settings.advancedIntervalGetFromApiExtra = 5;
settings.advancedIntervalGetFromBiliplus = 10;
settings.advancedIntervalGetFromJijidown = 10;
settings.advancedIntervalGetFromJijidownExtra = 10;
settings.advancedIntervalGetFromXbeibeix = 10;
settings.advancedIntervalAutoNextPage = 5;
GM_setValue('settings', settings);
}
///////////////////////////////////////////////////////////////////////////////////
const favlistObserver = new MutationObserver(async (_mutations, observer) => {
if (enableDebug) console.debug('callback favlistObserver');
if (document.querySelector('div.items')) {
if (enableDebug) console.debug('disconnect favlistObserver');
observer.disconnect();
newFreshSpace = true;
classAppendNewFreshSpace = '-newFreshSpace';
pageSize = window.innerWidth < 1760 ? 40 : 36;
initControls();
if (!firstTimeMain) {
await delay(200);
main();
}
if (enableDebug) console.debug('observe itemsObserver');
itemsObserver.observe(document.querySelector('div.items'), { childList: true, attributes: false, characterData: false });
if (enableDebug) console.debug('observe bodyChildListObserver');
bodyChildListObserver.observe(document.body, { childList: true, attributes: false, characterData: false });
if (enableDebug) console.debug('observe radioFilterObserver');
radioFilterObserver.observe(document.querySelector('div.fav-list-header-filter__left > div'), { subtree: true, characterData: false, attributeFilter: ['class'] });
if (enableDebug) console.debug('observe headerFilterLeftChildListObserver');
headerFilterLeftChildListObserver.observe(document.querySelector('div.fav-list-header-filter__left'), { childList: true, attributes: false, characterData: false });
return;
}
if (document.querySelector('div.fav-content.section')) {
if (enableDebug) console.debug('disconnect favlistObserver');
observer.disconnect();
newFreshSpace = false;
classAppendNewFreshSpace = '';
pageSize = 20;
initControls();
if (enableDebug) console.debug('observe favContentSectionObserver');
favContentSectionObserver.observe(document.querySelector('div.fav-content.section'), { characterData: false, attributeFilter: ['class'] });
return;
}
});
// const itemsObserver = new MutationObserver(async (mutations) => {
const itemsObserver = new MutationObserver(async () => {
abortActiveControllers();
if (enableDebug) console.debug('callback itemsObserver');
await delay(200);
// mainNewFreshSpace();
// mainNewFreshSpace(mutations);
main();
});
const bodyChildListObserver = new MutationObserver(mutations => {
if (enableDebug) console.debug('callback bodyChildListObserver');
if (enableDebug) console.debug(mutations);
for (const mutation of mutations) {
for (const addedNode of mutation.addedNodes) {
if (addedNode.nodeType === 1 && addedNode.classList.contains('bili-card-dropdown-popper')) {
appendDropdowns(addedNode);
// return;
}
// if (addedNode.nodeType === 1 && addedNode.classList.contains('vui_toast--wrapper')) {
// abortActiveControllers();
// if (enableDebug) console.debug('disconncet itemsObserver');
// itemsObserver.disconnect();
// // return;
// }
}
// for (const removedNode of mutation.removedNodes) {
// if (removedNode.nodeType === 1 && removedNode.classList.contains('vui_toast--wrapper')) {
// abortActiveControllers();
// // mainNewFreshSpace();
// main();
// if (enableDebug) console.debug('observe itemsObserver');
// itemsObserver.observe(document.querySelector('div.items'), { childList: true, attributes: false, characterData: false });
// // return;
// }
// }
}
});
const radioFilterObserver = new MutationObserver(mutations => {
if (enableDebug) console.debug('callback radioFilterObserver');
if (enableDebug) console.debug(mutations);
for (const mutation of mutations) {
if (mutation.target.classList.contains('radio-filter__item--active')) {
const orderText = mutation.target.innerText;
if (orderText.includes('收藏')) {
order = 'mtime';
} else if (orderText.includes('播放')) {
order = 'view';
} else if (orderText.includes('投稿')) {
order = 'pubtime';
} else {
addMessage('无法确定各个视频的排序方式, 请反馈该问题', false, true);
}
if (enableDebug) console.log(`order: ${order}`);
}
}
});
const headerFilterLeftChildListObserver = new MutationObserver(mutations => {
if (enableDebug) console.debug('callback headerFilterLeftChildListObserver');
if (enableDebug) console.debug(mutations);
for (const mutation of mutations) {
for (const addedNode of mutation.addedNodes) {
if (addedNode.nodeType === 1 && addedNode.classList.contains('radio-filter')) {
order = 'mtime';
if (enableDebug) console.log(`order: ${order}`);
if (enableDebug) console.debug('observe radioFilterObserver');
radioFilterObserver.observe(addedNode, { subtree: true, characterData: false, attributeFilter: ['class'] });
}
}
for (const removedNode of mutation.removedNodes) {
if (removedNode.nodeType === 1 && removedNode.classList.contains('radio-filter')) {
if (enableDebug) console.debug('disconncet radioFilterObserver');
radioFilterObserver.disconnect();
}
}
}
});
const favContentSectionObserver = new MutationObserver(mutations => {
if (enableDebug) console.debug('callback favContentSectionObserver');
for (const mutation of mutations) {
if (!mutation.target.classList.contains('loading')) {
abortActiveControllers();
main();
return;
}
}
});
checkURL();
const originalPushState = history.pushState;
history.pushState = function (...args) {
originalPushState.apply(this, args);
checkURL();
};
const originalReplaceState = history.replaceState;
history.replaceState = function (...args) {
originalReplaceState.apply(this, args);
checkURL();
};
window.addEventListener('popstate', checkURL);
function checkURL() {
if (enableDebug) console.debug('checkURL');
if (favlistURLRegex.test(location.href)) {
if (!onFavlistPage) {
onFavlistPage = true;
if (enableDebug) console.debug('observe favlistObserver');
favlistObserver.observe(document.body, { subtree: true, childList: true, attributes: false, characterData: false });
}
} else {
if (onFavlistPage) {
abortActiveControllers();
onFavlistPage = false;
if (enableDebug) console.debug('disconnect favlistObserver');
favlistObserver.disconnect();
if (enableDebug) console.debug('disconncet itemsObserver');
itemsObserver.disconnect();
if (enableDebug) console.debug('disconncet bodyChildListObserver');
bodyChildListObserver.disconnect();
if (enableDebug) console.debug('disconncet radioFilterObserver');
radioFilterObserver.disconnect();
if (enableDebug) console.debug('disconncet headerFilterLeftChildListObserver');
headerFilterLeftChildListObserver.disconnect();
if (enableDebug) console.debug('disconncet favContentSectionObserver');
favContentSectionObserver.disconnect();
}
}
}
async function main() {
if (enableDebug) console.log('============main============');
let controller;
firstTimeMain = false;
try {
controller = new AbortController();
activeControllers.add(controller);
let fid;
const getFidFromURLMatch = location.href.match(getFidFromURLRegex);
if (newFreshSpace) {
if (getFidFromURLMatch) {
fid = parseInt(getFidFromURLMatch[1], 10);
} else if (settings.defaultFavlistFid) {
fid = settings.defaultFavlistFid;
} else {
throw ['无法获取当前收藏夹的fid, 刷新页面可能有帮助'];
}
const getFtypeFromURLMatch = location.href.match(getFtypeFromURLRegex);
if (getFtypeFromURLMatch) {
if (getFtypeFromURLMatch[1] !== 'create') {
if (enableDebug) console.log('不处理特殊收藏夹');
return;
}
if (!settings.defaultFavlistFid && !document.querySelector('div.vui_sidebar-item--active').parentNode.getAttribute('id')) {
settings.defaultFavlistFid = fid;
GM_setValue('settings', settings);
}
} else if (!document.querySelector('div.vui_sidebar-item--active').parentNode.getAttribute('id') && fid !== settings.defaultFavlistFid) {
if (enableDebug) console.log('不处理特殊收藏夹');
return;
}
} else {
if (getFidFromURLMatch) {
fid = parseInt(getFidFromURLMatch[1], 10);
if (fid !== parseInt(document.querySelector('.fav-item.cur').getAttribute('fid'), 10)) {
if (enableDebug) console.log('不处理特殊收藏夹');
return;
}
} else {
fid = parseInt(document.querySelector('.fav-item.cur').getAttribute('fid'), 10);
if (!fid) {
if (enableDebug) console.log('不处理特殊收藏夹');
return;
}
}
}
let pageNumber;
if (newFreshSpace) {
const pagenation = document.querySelector('button.vui_pagenation--btn-num.vui_button--active');
if (!pagenation) {
pageNumber = 1;
} else {
pageNumber = parseInt(pagenation.innerText, 10);
}
} else {
pageNumber = parseInt(document.querySelector('li.be-pager-item-active > a').innerText, 10);
}
if (!settings.defaultUID) {
settings.defaultUID = parseInt(location.href.match(getUIDFromURLRegex)[1], 10);
GM_setValue('settings', settings);
}
const videos = document.querySelectorAll(newFreshSpace ? 'div.items__item' : 'li.small-item');
// if (fid !== fidOfAVBVs || !AVBVs) {
// if (controller.signal.aborted) {
// throw new DOMException('', 'AbortError');
// }
// const response = await new Promise((resolve, reject) => {
// GM.xmlHttpRequest({
// method: 'GET',
// url: `https://api.bilibili.com/x/v3/fav/resource/ids?media_id=${fid}&platform=web`,
// timeout: 5000,
// responseType: 'json',
// onload: (res) => resolve(res),
// onerror: (res) => reject(['请求失败', 'api.bilibili.com/x/v3/fav/resource/ids', res.error]),
// ontimeout: () => reject(['请求超时', 'api.bilibili.com/x/v3/fav/resource/ids'])
// });
// });
// if (enableDebug) console.log(`获取新的AVBVs, fid: ${fid}`);
// fidOfAVBVs = fid;
// AVBVs = response.response.data;
// }
// const clonedAVBVs = structuredClone(AVBVs);
const apiDetails = {};
for (const [index, video] of videos.entries()) {
let as;
const AVBVTitle = {
AV: null,
BV: null,
title: null
};
try {
if (controller.signal.aborted) {
throw new DOMException('', 'AbortError');
}
if (video.querySelector(newFreshSpace ? 'div.bili-cover-card__tags' : 'div.ogv-corner-tag')) {
if (enableDebug) console.log('不处理特殊视频');
continue;
}
let disabled = false;
if (newFreshSpace) {
if (!video.querySelector('div.bili-cover-card__stats')) {
disabled = true;
}
} else {
if (video.classList.contains('disabled')) {
disabled = true;
}
}
if (!settings.processNormal && !disabled) {
continue;
}
if (!settings.processDisabled && disabled) {
continue;
}
as = video.querySelectorAll('a');
const divTitleNewFreshSpace = video.querySelector('div.bili-video-card__title');
if (controller.signal.aborted) {
throw new DOMException('', 'AbortError');
}
if (newFreshSpace) {
const getBVFromURLMatch = as[0].getAttribute('href').match(getBVFromURLRegex);
if (!getBVFromURLMatch) {
throw ['无法获取该视频的BV号, 请检查是否有其他脚本或插件修改了该视频封面和标题的链接地址, 并将其关闭'];
}
AVBVTitle.BV = getBVFromURLMatch[1];
} else {
AVBVTitle.BV = video.getAttribute('data-aid');
}
// const target = clonedAVBVs.find(el => el.bvid === AVBVTitle.BV);
// if (target) {
// AVBVTitle.AV = target.id;
// }
AVBVTitle.title = as[1].innerText;
if (enableDebug) console.log('========video========');
if (enableDebug) console.log(`收藏夹fid: ${fid}`);
if (enableDebug) console.log(`位置: 第${pageNumber}页的第${index + 1}个`);
if (enableDebug) consoleAVBVTitle('log', AVBVTitle);
let spanFavTime;
let divTCABJX;
if (newFreshSpace) {
const divSubtitle = document.createElement('div');
divSubtitle.classList.add('bili-video-card__subtitle');
video.querySelector('div.bili-video-card__details').appendChild(divSubtitle);
spanFavTime = document.createElement('span');
spanFavTime.textContent = '投稿于:';
divSubtitle.appendChild(spanFavTime);
divTCABJX = document.createElement('div');
divTCABJX.style.marginLeft = 'auto';
divTCABJX.style.display = 'block';
divSubtitle.appendChild(divTCABJX);
} else {
const divMetaPubdate = video.querySelector('div.meta.pubdate');
const metaText = divMetaPubdate.innerText;
divMetaPubdate.innerHTML = null;
spanFavTime = document.createElement('span');
spanFavTime.textContent = metaText.replace(': ', ':');
spanFavTime.style.width = 'auto';
spanFavTime.style.lineHeight = '16px';
divMetaPubdate.appendChild(spanFavTime);
// divTCABJX = document.createElement('div');
// divTCABJX.style.marginLeft = 'auto';
// // divTCABJX.style.display = 'block';
// divMetaPubdate.appendChild(divTCABJX);
divTCABJX = divMetaPubdate;
}
const spanX = document.createElement('span');
spanX.classList.add('backup-spanTCABJX' + classAppendNewFreshSpace);
spanX.textContent = 'X';
if (!newFreshSpace) {
// spanX.style.marginRight = '11px';
spanX.style.marginRight = '9px';
spanX.style.lineHeight = '16px';
}
spanX.addEventListener('click', () => {
try {
GM_openInTab(`https://${settings.getFromXbeibeixURL}/video/${AVBVTitle.BV}`, { active: true, insert: false, setParent: true });
} catch (error) {
catchUnknownError(error);
}
});
divTCABJX.appendChild(spanX);
const spanJ = document.createElement('span');
spanJ.classList.add('backup-spanTCABJX' + classAppendNewFreshSpace);
spanJ.textContent = 'J';
spanJ.style.marginRight = '3px';
if (!newFreshSpace) {
spanJ.style.lineHeight = '16px';
}
spanJ.addEventListener('click', () => {
try {
GM_openInTab(`https://${settings.getFromJijidownURL}/video/${AVBVTitle.BV}`, { active: true, insert: false, setParent: true });
if (enableDebug) {
GM_openInTab(`https://${settings.getFromJijidownURL}/api/v1/video_bv/get_info?id=${AVBVTitle.BV.slice(2)}`, { insert: false, setParent: true });
GM_openInTab(`https://${settings.getFromJijidownURL}/api/v1/video_bv/get_download_info?id=${AVBVTitle.BV.slice(2)}`, { insert: false, setParent: true });
}
} catch (error) {
catchUnknownError(error);
}
});
divTCABJX.appendChild(spanJ);
const spanB = document.createElement('span');
spanB.classList.add('backup-spanTCABJX' + classAppendNewFreshSpace);
spanB.textContent = 'B';
spanB.style.marginRight = '3px';
if (!newFreshSpace) {
spanB.style.lineHeight = '16px';
}
spanB.addEventListener('click', () => {
try {
GM_openInTab(`https://www.biliplus.com/video/${AVBVTitle.BV}`, { active: true, insert: false, setParent: true });
if (enableDebug) {
if (AVBVTitle.AV) {
GM_openInTab(`https://www.biliplus.com/api/view?id=${AVBVTitle.AV}`, { insert: false, setParent: true });
} else {
GM_openInTab(`https://www.biliplus.com/api/view?id=${AVBVTitle.BV}`, { insert: false, setParent: true });
}
}
} catch (error) {
catchUnknownError(error);
}
});
divTCABJX.appendChild(spanB);
const spanA = document.createElement('span');
spanA.classList.add('backup-spanTCABJX' + classAppendNewFreshSpace);
spanA.textContent = 'A';
spanA.style.marginRight = '3px';
if (!newFreshSpace) {
spanA.style.lineHeight = '16px';
}
spanA.addEventListener('click', async () => {
try {
GM_openInTab(`https://api.bilibili.com/x/web-interface/view?bvid=${AVBVTitle.BV}`, { active: true, insert: false, setParent: true });
if (enableDebug) {
GM_openInTab(`https://api.bilibili.com/x/web-interface/archive/desc?bvid=${AVBVTitle.BV}`, { insert: false, setParent: true });
if (AVBVTitle.AV) {
GM_openInTab(`https://api.bilibili.com/x/v3/fav/resource/infos?resources=${AVBVTitle.AV}%3A2&platform=web&folder_id=${fid}`, { insert: false, setParent: true });
}
GM_openInTab(await appendParamsForGetFromApi(fid, ((pageNumber - 1) * pageSize + index + 1), 1), { insert: false, setParent: true });
}
} catch (error) {
catchUnknownError(error);
}
});
divTCABJX.appendChild(spanA);
const backup = GM_getValue(AVBVTitle.BV, {
BV: null,
AV: null,
title: null,
intro: null,
cover: null,
upperUID: null,
upperName: null,
upperAvatar: null,
timeUpload: null,
timePublish: null,
timeFavorite: null,
dynamic: null,
pages: null,
api: null,
apiExtra: null,
biliplus: null,
jijidown: null,
jijidownExtra: null,
xbeibeix: null,
// preferredTitle: null,
// preferredCover: null,
});
if (!backup.BV) {
backup.BV = AVBVTitle.BV;
// backup.AV = AVBVTitle.AV;
GM_setValue(AVBVTitle.BV, backup);
}
AVBVTitle.AV = backup.AV;
if (updateTimeFavoriteInBackup(backup, undefined, fid)) {
GM_setValue(AVBVTitle.BV, backup);
}
///////////////////////////////////////////////////////////////////////////////////
// v9
if (backup.timeFavorite) {
let modified = false;
backup.timeFavorite.forEach(el => {
if (typeof el.fid === 'string') {
el.fid = parseInt(el.fid, 10);
modified = true;
}
});
if (modified) {
GM_setValue(AVBVTitle.BV, backup);
}
}
// v9
if (backup.timeUpload && typeof backup.timeUpload === 'object') {
if (backup.timeUpload.length === 1) {
backup.timeUpload = backup.timeUpload[0].value;
} else {
backup.timeUpload = null;
}
GM_setValue(AVBVTitle.BV, backup);
}
// v9
if (backup.timePublish && typeof backup.timePublish === 'object') {
if (backup.timePublish.length === 1) {
backup.timePublish = backup.timePublish[0].value;
} else {
backup.timePublish = null;
}
GM_setValue(AVBVTitle.BV, backup);
}
// v10
if (backup.hasOwnProperty('jiji')) {
backup.jijidown = backup.jiji;
delete backup.jiji;
GM_setValue(AVBVTitle.BV, backup);
}
// v10
if (backup.hasOwnProperty('bbdownloader')) {
backup.xbeibeix = backup.bbdownloader;
delete backup.bbdownloader;
GM_setValue(AVBVTitle.BV, backup);
}
// v12
['cover', 'upperAvatar'].forEach(key => {
if (backup[key] && backup[key].length > 1) {
const tempBackup = {};
backup[key].forEach(el => {
updateArrayDataInBackup(tempBackup, key, el.value, el.ts, el.from);
});
backup[key] = tempBackup[key];
GM_setValue(AVBVTitle.BV, backup);
}
});
// v14
if (backup.hasOwnProperty('firstFrame')) {
delete backup.firstFrame;
GM_setValue(AVBVTitle.BV, backup);
}
// v16
if (backup.intro) {
const tempBackup = { intro: null };
backup.intro.forEach(el => {
updateArrayDataInBackup(tempBackup, 'intro', el.value, el.ts, el.from);
});
backup.intro = tempBackup.intro;
GM_setValue(AVBVTitle.BV, backup);
}
///////////////////////////////////////////////////////////////////////////////////
const functions = [];
try {
if (newFreshSpace) {
if (backup.timePublish) {
spanFavTime.textContent = `投稿于:${formatTsTimePublish(backup.timePublish * 1000)}`;
spanFavTime.setAttribute('title', new Date(backup.timePublish * 1000).toLocaleString());
}
} else {
if (backup.timeFavorite) {
const target = backup.timeFavorite.find(el => el.fid === fid);
if (target) {
spanFavTime.textContent = `收藏于:${formatTsTimeFavorite(new Date(target.value * 1000))}`;
spanFavTime.setAttribute('title', new Date(target.value * 1000).toLocaleString());
}
}
}
if (settings.enableGetFromApi) {
if (!backup.api || (!settings.advancedDisableUpdateGetFromApi && getCurrentTs() - backup.api.ts > 3600 * settings.advancedIntervalGetFromApi)) {
const skip = await getFromApi(AVBVTitle, backup, spanA, apiDetails, fid, pageNumber, disabled, spanFavTime);
if (skip) {
continue;
}
} else {
spanA.style.color = backup.api.value ? '#00ff00' : '#ff0000';
if (apiDetails.value) {
const apiDetail = apiDetails.value.find(el => el.bvid === AVBVTitle.BV);
if (apiDetail) {
if (updateTimeFavoriteInBackup(backup, apiDetail.fav_time, fid)) {
GM_setValue(AVBVTitle.BV, backup);
}
}
}
}
}
if (settings.enableGetFromApiExtra) {
if (!backup.apiExtra || (!settings.advancedDisableUpdateGetFromApiExtra && getCurrentTs() - backup.apiExtra.ts > 3600 * 24 * settings.advancedIntervalGetFromApiExtra)) {
await getFromApiExtra(AVBVTitle, backup, spanA, disabled);
} else {
spanA.style.color = backup.apiExtra.value ? '#008000' : '#800000';
}
}
if (settings.enableGetFromJijidown) {
if (!backup.jijidown || (!settings.advancedDisableUpdateGetFromJijidown && getCurrentTs() - backup.jijidown.ts > 3600 * 24 * 7 * settings.advancedIntervalGetFromJijidown)) {
functions.push(getFromJijidown(AVBVTitle, backup, spanJ));
} else {
if (settings.enableGetFromJijidownExtra) {
if (!backup.jijidownExtra || (!settings.advancedDisableUpdateGetFromJijidownExtra && getCurrentTs() - backup.jijidownExtra.ts > 3600 * 24 * 7 * settings.advancedIntervalGetFromJijidownExtra)) {
functions.push(getFromJijidown(AVBVTitle, backup, spanJ));
} else {
spanJ.style.color = backup.jijidownExtra.value ? '#008000' : '#800000';
}
} else {
spanJ.style.color = backup.jijidown.value ? '#00ff00' : '#ff0000';
}
}
}
if (settings.enableGetFromXbeibeix) {
if (!backup.xbeibeix || (!settings.advancedDisableUpdateGetFromXbeibeix && getCurrentTs() - backup.xbeibeix.ts > 3600 * 24 * 7 * settings.advancedIntervalGetFromXbeibeix)) {
functions.push(getFromXbeibeix(AVBVTitle, backup, spanX));
} else {
spanX.style.color = backup.xbeibeix.value ? '#00ff00' : '#ff0000';
}
}
if (settings.enableGetFromBiliplus) {
if (!backup.biliplus || (!settings.advancedDisableUpdateGetFromBiliplus && getCurrentTs() - backup.biliplus.ts > 3600 * 24 * 7 * settings.advancedIntervalGetFromBiliplus)) {
functions.push(getFromBiliplus(AVBVTitle, backup, spanB));
} else {
spanB.style.color = backup.biliplus.value ? '#00ff00' : '#ff0000';
}
}
if (functions.length) {
if (controller.signal.aborted) {
throw new DOMException('', 'AbortError');
}
await Promise.all(functions);
const sortedBackup = {};
for (const sortedKey of sortedKeys) {
sortedBackup[sortedKey] = backup[sortedKey];
}
GM_setValue(AVBVTitle.BV, sortedBackup);
if (enableDebug) console.log('保存第三方网站的数据至本地');
if (enableDebug) consoleAVBVTitle('debug', AVBVTitle);
if (enableDebug) console.debug(sortedBackup);
}
} catch (error) {
if (error instanceof Error) {
if (error.name === 'AbortError') {
throw error;
}
addMessage('发生未知错误, 请反馈该问题', false, true);
addMessage(`收藏夹fid: ${fid}`, true);
addMessage(`位置: 第${pageNumber}页的第${index + 1}个`, true);
addMessageAVBVTitle(AVBVTitle);
addMessage(error.stack, true);
console.error(`收藏夹fid: ${fid}`);
console.error(`位置: 第${pageNumber}页的第${index + 1}个`);
consoleAVBVTitle('error', AVBVTitle);
console.error(error);
if (as[1]) {
as[1].style.color = '#ff0000';
}
} else {
addMessage(error[0], false, true);
for (let i = 1; i < error.length; i++) {
addMessage(error[i], true);
}
addMessage(`收藏夹fid: ${fid}`, true);
addMessage(`位置: 第${pageNumber}页的第${index + 1}个`, true);
addMessageAVBVTitle(AVBVTitle);
if (as[1]) {
as[1].style.color = '#ff0000';
}
}
}
let picture;
let sourceAvif;
let sourceWebp;
let img;
if (newFreshSpace) {
img = video.querySelector('img');
} else {
picture = video.querySelector('picture');
sourceAvif = picture.querySelector('source[type="image/avif"]');
sourceWebp = picture.querySelector('source[type="image/webp"]');
img = picture.querySelector('img');
}
if (disabled) {
// video.style.opacity = '0.7';
if (newFreshSpace) {
as[2].style.textDecoration = 'line-through';
as[2].style.opacity = '0.7';
if (backup.cover) {
img.setAttribute('src', `//${backup.cover[backup.cover.length - 1].value}@672w_378h_1c.avif`);
}
} else {
video.classList.remove('disabled');
as[0].classList.remove('disabled');
as[0].setAttribute('href', `//www.bilibili.com/video/${AVBVTitle.BV}/`);
as[0].setAttribute('target', '_blank');
as[1].setAttribute('target', '_blank');
as[1].setAttribute('href', `//www.bilibili.com/video/${AVBVTitle.BV}/`);
if (backup.cover) {
sourceAvif.setAttribute('srcset', `//${backup.cover[backup.cover.length - 1].value}@320w_200h_1c_!web-space-favlist-video.avif`);
sourceWebp.setAttribute('srcset', `//${backup.cover[backup.cover.length - 1].value}@320w_200h_1c_!web-space-favlist-video.webp`);
img.setAttribute('src', `//${backup.cover[backup.cover.length - 1].value}@320w_200h_1c_!web-space-favlist-video.webp`);
}
}
spanFavTime.style.textDecoration = 'line-through';
spanFavTime.style.opacity = '0.7';
as[1].style.textDecoration = 'line-through';
as[1].style.opacity = '0.5';
if (backup.title) {
as[1].textContent = backup.title[backup.title.length - 1].value;
img.setAttribute('alt', backup.title[backup.title.length - 1].value);
if (newFreshSpace) {
divTitleNewFreshSpace.setAttribute('title', backup.title[backup.title.length - 1].value);
} else {
as[1].setAttribute('title', backup.title[backup.title.length - 1].value);
}
}
}
if (backup.cover && backup.cover.length > 1) {
const spanC = document.createElement('span');
spanC.classList.add('backup-spanTCABJX' + classAppendNewFreshSpace);
spanC.textContent = 'C';
spanC.style.marginRight = '3px';
spanC.style.color = '#000000';
if (!newFreshSpace) {
spanC.style.lineHeight = '16px';
}
let i = backup.cover.length - 2;
spanC.addEventListener('click', () => {
try {
if (i < 0) {
i = backup.cover.length - 1;
}
if (newFreshSpace) {
img.setAttribute('src', `//${backup.cover[i].value}@672w_378h_1c.avif`);
} else {
sourceAvif.setAttribute('srcset', `//${backup.cover[i].value}@320w_200h_1c_!web-space-favlist-video.avif`);
sourceWebp.setAttribute('srcset', `//${backup.cover[i].value}@320w_200h_1c_!web-space-favlist-video.webp`);
img.setAttribute('src', `//${backup.cover[i].value}@320w_200h_1c_!web-space-favlist-video.webp`);
}
if (i !== backup.cover.length - 1) {
spanC.style.color = '#999999';
} else {
spanC.style.color = '#000000';
}
i--;
} catch (error) {
catchUnknownError(error);
}
});
divTCABJX.appendChild(spanC);
}
if (backup.title && backup.title.length > 1) {
const spanT = document.createElement('span');
spanT.classList.add('backup-spanTCABJX' + classAppendNewFreshSpace);
spanT.textContent = 'T';
spanT.style.marginRight = '3px';
spanT.style.color = '#000000';
if (!newFreshSpace) {
spanT.style.lineHeight = '16px';
}
let i = backup.title.length - 2;
spanT.addEventListener('click', () => {
try {
if (i < 0) {
i = backup.title.length - 1;
}
as[1].textContent = backup.title[i].value;
if (newFreshSpace) {
divTitleNewFreshSpace.setAttribute('title', backup.title[i].value);
} else {
as[1].setAttribute('title', backup.title[i].value);
}
if (i !== backup.title.length - 1) {
spanT.style.color = '#999999';
} else {
spanT.style.color = '#000000';
}
i--;
} catch (error) {
catchUnknownError(error);
}
});
divTCABJX.appendChild(spanT);
}
if (controller.signal.aborted) {
throw new DOMException('', 'AbortError');
}
if (!newFreshSpace) {
const ul = video.querySelector('ul.be-dropdown-menu');
if (ul) {
appendDropdowns(ul, AVBVTitle.BV);
}
}
if (functions.length === 1) {
await delay(200);
}
} catch (error) {
if (error instanceof Error) {
if (error.name === 'AbortError') {
throw error;
}
addMessage('发生未知错误, 请反馈该问题', false, true);
addMessage(`收藏夹fid: ${fid}`, true);
addMessage(`位置: 第${pageNumber}页的第${index + 1}个`, true);
addMessageAVBVTitle(AVBVTitle);
addMessage(error.stack, true);
console.error(`收藏夹fid: ${fid}`);
console.error(`位置: 第${pageNumber}页的第${index + 1}个`);
consoleAVBVTitle('error', AVBVTitle);
console.error(error);
if (as[1]) {
as[1].style.color = '#ff0000';
}
} else {
addMessage(error[0], false, true);
for (let i = 1; i < error.length; i++) {
addMessage(error[i], true);
}
addMessage(`收藏夹fid: ${fid}`, true);
addMessage(`位置: 第${pageNumber}页的第${index + 1}个`, true);
addMessageAVBVTitle(AVBVTitle);
if (as[1]) {
as[1].style.color = '#ff0000';
}
}
}
}
if (enableAutoNextPage) {
if (newFreshSpace) {
const pager = Array.from(document.querySelectorAll('button.vui_pagenation--btn-side')).find(el => el.innerText === '下一页');
if (pager && !pager.classList.contains('vui_button--disabled')) {
await delay(1000 * settings.advancedIntervalAutoNextPage);
if (controller.signal.aborted) {
throw new DOMException('', 'AbortError');
}
if (enableAutoNextPage) {
pager.click();
}
}
} else {
const pager = document.querySelector('li.be-pager-next');
if (pager && !pager.classList.contains('be-pager-disabled')) {
await delay(1000 * settings.advancedIntervalAutoNextPage);
if (controller.signal.aborted) {
throw new DOMException('', 'AbortError');
}
if (enableAutoNextPage) {
pager.click();
}
}
}
}
} catch (error) {
if (error instanceof Error) {
if (error.name === 'AbortError') {
return;
}
catchUnknownError(error);
} else {
addMessage(error[0], false, true);
for (let i = 1; i < error.length; i++) {
addMessage(error[i], true);
}
}
} finally {
activeControllers.delete(controller);
}
}
function initControls() {
let displayUpdate = false;
if (settings.version !== version) {
if (settings.version) {
displayUpdate = true;
}
settings.version = version;
GM_setValue('settings', settings);
}
const style = document.createElement('style');
style.textContent = `
.backup-spanTCABJX, .backup-spanTCABJX-newFreshSpace {
float: right;
font-weight: bold;
cursor: pointer;
}
.backup-div-first {
padding: 2px;
}
.backup-div-first-newFreshSpace {
padding: 2px 0;
}
.backup-div-second {
padding: 2px 0 2px 9px;
}
.backup-div-second-newFreshSpace {
padding: 2px 0 2px 8px;
}
.backup-div-third {
padding: 2px 0 2px 16px;
}
.backup-div-third-newFreshSpace {
padding: 2px 0 2px 16px;
}
.backup-label, .backup-label-newFreshSpace {
line-height: 1;
}
.backup-disabled, .backup-disabled-newFreshSpace {
opacity: 0.5;
pointer-events: none;
}
.backup-inputText, .backup-inputText-newFreshSpace {
box-sizing: content-box;
border: 1px solid #cccccc;
padding: 1px 2px;
line-height: 1;
}
.backup-inputText {
width: 25px;
height: 14px;
border-radius: 2px;
font-size: 14px;
}
.backup-inputText-newFreshSpace {
width: 30px;
height: 16px;
border-radius: 3px;
font-size: 16px;
}
.backup-hidden, .backup-hidden-newFreshSpace {
display: none;
}
.backup-button, .backup-button-newFreshSpace {
border: 1px solid #cccccc;
line-height: 1;
cursor: pointer;
}
.backup-button {
border-radius: 2px;
padding: 2px;
font-size: 14px;
}
.backup-button-newFreshSpace {
border-radius: 3px;
padding: 3px;
font-size: 16px;
}
.backup-divMessage, .backup-divMessage-newFreshSpace {
overflow-y: auto;
background-color: #eeeeee;
line-height: 1.5;
scrollbar-width: none;
}
.backup-divMessage {
margin: 2px;
}
.backup-divMessage-heightFixed {
height: 280px;
}
.backup-divMessage::-webkit-scrollbar {
display: none;
}
.backup-divMessage-newFreshSpace {
margin: 2px 0;
}
.backup-divMessage-heightFixed-newFreshSpace {
height: 320px;
}
.backup-divMessage-newFreshSpace::-webkit-scrollbar {
display: none;
}
`;
document.head.appendChild(style);
const divSide = document.querySelector(newFreshSpace ? 'div.favlist-aside' : 'div.fav-sidenav');
if (!newFreshSpace && divSide.querySelector('a.watch-later')) {
divSide.querySelector('a.watch-later').style.borderBottom = '1px solid #eeeeee';
}
const divControls = document.createElement('div');
divControls.classList.add('backup-div-first' + classAppendNewFreshSpace);
if (!newFreshSpace) {
divControls.style.borderTop = '1px solid #e4e9f0';
}
divSide.appendChild(divControls);
const divLabelProcessNormal = document.createElement('div');
divLabelProcessNormal.classList.add('backup-div-first' + classAppendNewFreshSpace);
divLabelProcessNormal.setAttribute('title',
'默认: 开启\n' +
'由于新视频的BV号随机生成, 各个第三方网站无法自动地爬取新视频的信息。\n' +
'开启该选项的同时开启下面的从第三方网站获取数据, 脚本将代替您访问相应的第三方网站。\n' +
'如果处理的视频第三方网站还没有备份, 这将使其备份该视频当前版本的信息。\n' +
'如果处理的视频之前有人备份过了, 这将获取到该视频的信息备份到第三方网站时的版本。');
divControls.appendChild(divLabelProcessNormal);
const labelProcessNormal = document.createElement('label');
labelProcessNormal.classList.add('backup-label' + classAppendNewFreshSpace);
labelProcessNormal.textContent = '处理正常视频';
divLabelProcessNormal.appendChild(labelProcessNormal);
const checkboxProcessNormal = document.createElement('input');
checkboxProcessNormal.type = 'checkbox';
checkboxProcessNormal.checked = settings.processNormal;
checkboxProcessNormal.addEventListener('change', () => {
try {
settings.processNormal = checkboxProcessNormal.checked;
GM_setValue('settings', settings);
if (!settings.processNormal && !settings.processDisabled) {
divLabelEnableGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL1.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL2.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL1.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL2.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelEnableGetFromApi.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromApi) {
divLabelAdvancedDisableUpdateGetFromApi.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromApi) {
divLabelAdvancedIntervalGetFromApi.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divLabelEnableGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromApiExtra) {
divLabelAdvancedDisableUpdateGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromApiExtra) {
divLabelAdvancedIntervalGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
}
divLabelEnableGetFromBiliplus.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromBiliplus) {
divLabelAdvancedDisableUpdateGetFromBiliplus.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromBiliplus) {
divLabelAdvancedIntervalGetFromBiliplus.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
divLabelEnableGetFromJijidown.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromJijidown) {
divLabelAdvancedDisableUpdateGetFromJijidown.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromJijidown) {
divLabelAdvancedIntervalGetFromJijidown.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divLabelEnableGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromJijidownExtra) {
divLabelAdvancedDisableUpdateGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromJijidownExtra) {
divLabelAdvancedIntervalGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
divSwitchGetFromJijidownURL1.classList.remove('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL2.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divLabelEnableGetFromXbeibeix.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromXbeibeix) {
divLabelAdvancedDisableUpdateGetFromXbeibeix.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromXbeibeix) {
divLabelAdvancedIntervalGetFromXbeibeix.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divSwitchGetFromXbeibeixURL1.classList.remove('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL2.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
} catch (error) {
catchUnknownError(error);
}
});
labelProcessNormal.insertAdjacentElement('afterbegin', checkboxProcessNormal);
const divLabelProcessDisabled = document.createElement('div');
divLabelProcessDisabled.classList.add('backup-div-first' + classAppendNewFreshSpace);
divLabelProcessDisabled.setAttribute('title',
'默认: 开启\n' +
'开启该选项的同时开启下面的从第三方网站获取数据, 脚本将尝试从相应的第三方网站获取失效视频的信息。');
divControls.appendChild(divLabelProcessDisabled);
const labelProcessDisabled = document.createElement('label');
labelProcessDisabled.classList.add('backup-label' + classAppendNewFreshSpace);
labelProcessDisabled.textContent = '处理失效视频';
divLabelProcessDisabled.appendChild(labelProcessDisabled);
const checkboxProcessDisabled = document.createElement('input');
checkboxProcessDisabled.type = 'checkbox';
checkboxProcessDisabled.checked = settings.processDisabled;
checkboxProcessDisabled.addEventListener('change', () => {
try {
settings.processDisabled = checkboxProcessDisabled.checked;
GM_setValue('settings', settings);
if (!settings.processNormal && !settings.processDisabled) {
divLabelEnableGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL1.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL2.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL1.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL2.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelEnableGetFromApi.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromApi) {
divLabelAdvancedDisableUpdateGetFromApi.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromApi) {
divLabelAdvancedIntervalGetFromApi.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divLabelEnableGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromApiExtra) {
divLabelAdvancedDisableUpdateGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromApiExtra) {
divLabelAdvancedIntervalGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
}
divLabelEnableGetFromBiliplus.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromBiliplus) {
divLabelAdvancedDisableUpdateGetFromBiliplus.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromBiliplus) {
divLabelAdvancedIntervalGetFromBiliplus.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
divLabelEnableGetFromJijidown.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromJijidown) {
divLabelAdvancedDisableUpdateGetFromJijidown.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromJijidown) {
divLabelAdvancedIntervalGetFromJijidown.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divLabelEnableGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromJijidownExtra) {
divLabelAdvancedDisableUpdateGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromJijidownExtra) {
divLabelAdvancedIntervalGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
divSwitchGetFromJijidownURL1.classList.remove('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL2.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divLabelEnableGetFromXbeibeix.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromXbeibeix) {
divLabelAdvancedDisableUpdateGetFromXbeibeix.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromXbeibeix) {
divLabelAdvancedIntervalGetFromXbeibeix.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divSwitchGetFromXbeibeixURL1.classList.remove('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL2.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
} catch (error) {
catchUnknownError(error);
}
});
labelProcessDisabled.insertAdjacentElement('afterbegin', checkboxProcessDisabled);
const divLabelEnableGetFromApi = document.createElement('div');
divLabelEnableGetFromApi.classList.add('backup-div-second' + classAppendNewFreshSpace);
divLabelEnableGetFromApi.setAttribute('title',
'默认: 开启\n' +
'地址: https://api.bilibili.com/x/v3/fav/resource/list?media_id={收藏夹fid}&pn={页码}&ps={每页展示视频数量}\n' +
'数据: AV号, 标题 (失效视频无法获取), 简介 (仅能获取前255个字符), 封面地址 (失效视频无法获取), UP主UID, UP主昵称, UP主头像地址, 上传时间, 发布时间, 添加到当前收藏夹的时间 (均为最新版本)\n' +
'地址: https://api.bilibili.com/x/web-interface/archive/desc?bvid={BV号}\n' +
'数据: 完整简介 (最新版本, 非必要不会调用该接口)');
divControls.appendChild(divLabelEnableGetFromApi);
const labelEnableGetFromApi = document.createElement('label');
labelEnableGetFromApi.classList.add('backup-label' + classAppendNewFreshSpace);
labelEnableGetFromApi.textContent = '从B站接口获取数据';
divLabelEnableGetFromApi.appendChild(labelEnableGetFromApi);
const checkboxEnableGetFromApi = document.createElement('input');
checkboxEnableGetFromApi.type = 'checkbox';
checkboxEnableGetFromApi.checked = settings.enableGetFromApi;
checkboxEnableGetFromApi.addEventListener('change', () => {
try {
settings.enableGetFromApi = checkboxEnableGetFromApi.checked;
if (!settings.enableGetFromApi) {
settings.enableGetFromApiExtra = false;
checkboxEnableGetFromApiExtra.checked = false;
divLabelAdvancedDisableUpdateGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelAdvancedDisableUpdateGetFromApi.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromApi) {
divLabelAdvancedIntervalGetFromApi.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divLabelEnableGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromApiExtra) {
divLabelAdvancedDisableUpdateGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromApiExtra) {
divLabelAdvancedIntervalGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableGetFromApi.insertAdjacentElement('afterbegin', checkboxEnableGetFromApi);
const divLabelAdvancedDisableUpdateGetFromApi = document.createElement('div');
divLabelAdvancedDisableUpdateGetFromApi.classList.add('backup-div-third' + classAppendNewFreshSpace, 'backup-advanced');
divLabelAdvancedDisableUpdateGetFromApi.setAttribute('title',
'默认: 关闭\n' +
'开启后每个视频从B站接口只会获取一次数据。\n' +
'不建议开启, 因为某些视频的信息可能会经常更新。');
divControls.appendChild(divLabelAdvancedDisableUpdateGetFromApi);
const labelAdvancedDisableUpdateGetFromApi = document.createElement('label');
labelAdvancedDisableUpdateGetFromApi.classList.add('backup-label' + classAppendNewFreshSpace);
labelAdvancedDisableUpdateGetFromApi.textContent = '禁用更新';
divLabelAdvancedDisableUpdateGetFromApi.appendChild(labelAdvancedDisableUpdateGetFromApi);
const checkboxAdvancedDisableUpdateGetFromApi = document.createElement('input');
checkboxAdvancedDisableUpdateGetFromApi.type = 'checkbox';
checkboxAdvancedDisableUpdateGetFromApi.checked = settings.advancedDisableUpdateGetFromApi;
checkboxAdvancedDisableUpdateGetFromApi.addEventListener('change', () => {
try {
settings.advancedDisableUpdateGetFromApi = checkboxAdvancedDisableUpdateGetFromApi.checked;
if (settings.advancedDisableUpdateGetFromApi) {
divLabelAdvancedIntervalGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelAdvancedIntervalGetFromApi.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelAdvancedDisableUpdateGetFromApi.insertAdjacentElement('afterbegin', checkboxAdvancedDisableUpdateGetFromApi);
const divLabelAdvancedIntervalGetFromApi = document.createElement('div');
divLabelAdvancedIntervalGetFromApi.classList.add('backup-div-third' + classAppendNewFreshSpace, 'backup-advanced');
divLabelAdvancedIntervalGetFromApi.setAttribute('title',
'默认: 5小时\n' +
'脚本处理某个视频时, 如果发现距离上次从B站接口获取到该视频的数据已经超过了设定的时间间隔, 则会再次从B站接口获取该视频的数据。');
divControls.appendChild(divLabelAdvancedIntervalGetFromApi);
const labelAdvancedIntervalGetFromApi = document.createElement('label');
labelAdvancedIntervalGetFromApi.classList.add('backup-label' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromApi.appendChild(labelAdvancedIntervalGetFromApi);
const inputTextAdvancedIntervalGetFromApi = document.createElement('input');
inputTextAdvancedIntervalGetFromApi.type = 'text';
inputTextAdvancedIntervalGetFromApi.classList.add('backup-inputText' + classAppendNewFreshSpace);
inputTextAdvancedIntervalGetFromApi.value = settings.advancedIntervalGetFromApi;
inputTextAdvancedIntervalGetFromApi.setAttribute('backup-def', 5);
inputTextAdvancedIntervalGetFromApi.setAttribute('backup-min', 1);
inputTextAdvancedIntervalGetFromApi.setAttribute('backup-max', 100);
inputTextAdvancedIntervalGetFromApi.setAttribute('backup-setting', 'advancedIntervalGetFromApi');
inputTextAdvancedIntervalGetFromApi.addEventListener('blur', validateInputText);
labelAdvancedIntervalGetFromApi.appendChild(document.createTextNode('最小更新间隔'))
labelAdvancedIntervalGetFromApi.appendChild(inputTextAdvancedIntervalGetFromApi);
labelAdvancedIntervalGetFromApi.appendChild(document.createTextNode('小时'));
const divLabelEnableGetFromApiExtra = document.createElement('div');
divLabelEnableGetFromApiExtra.classList.add('backup-div-second' + classAppendNewFreshSpace);
divLabelEnableGetFromApiExtra.setAttribute('title',
'默认: 关闭\n' +
'地址: https://api.bilibili.com/x/web-interface/view?bvid={BV号}\n' +
'数据: 完整简介, 视频发布动态内容, 每个分集的标题, 第1帧截图地址 (旧视频无法获取), cid (均为最新版本, 失效视频均无法获取, 不会调用该接口)');
divControls.appendChild(divLabelEnableGetFromApiExtra);
const labelEnableGetFromApiExtra = document.createElement('label');
labelEnableGetFromApiExtra.classList.add('backup-label' + classAppendNewFreshSpace);
labelEnableGetFromApiExtra.textContent = '从B站接口获取额外数据';
divLabelEnableGetFromApiExtra.appendChild(labelEnableGetFromApiExtra);
const checkboxEnableGetFromApiExtra = document.createElement('input');
checkboxEnableGetFromApiExtra.type = 'checkbox';
checkboxEnableGetFromApiExtra.checked = settings.enableGetFromApiExtra;
checkboxEnableGetFromApiExtra.addEventListener('change', () => {
try {
settings.enableGetFromApiExtra = checkboxEnableGetFromApiExtra.checked;
if (!settings.enableGetFromApiExtra) {
divLabelAdvancedDisableUpdateGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelAdvancedDisableUpdateGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromApiExtra) {
divLabelAdvancedIntervalGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableGetFromApiExtra.insertAdjacentElement('afterbegin', checkboxEnableGetFromApiExtra);
const divLabelAdvancedDisableUpdateGetFromApiExtra = document.createElement('div');
divLabelAdvancedDisableUpdateGetFromApiExtra.classList.add('backup-div-third' + classAppendNewFreshSpace, 'backup-advanced');
divLabelAdvancedDisableUpdateGetFromApiExtra.setAttribute('title',
'默认: 关闭\n' +
'不建议开启, 因为某些视频的信息可能会经常更新。');
divControls.appendChild(divLabelAdvancedDisableUpdateGetFromApiExtra);
const labelAdvancedDisableUpdateGetFromApiExtra = document.createElement('label');
labelAdvancedDisableUpdateGetFromApiExtra.classList.add('backup-label' + classAppendNewFreshSpace);
labelAdvancedDisableUpdateGetFromApiExtra.textContent = '禁用更新';
divLabelAdvancedDisableUpdateGetFromApiExtra.appendChild(labelAdvancedDisableUpdateGetFromApiExtra);
const checkboxAdvancedDisableUpdateGetFromApiExtra = document.createElement('input');
checkboxAdvancedDisableUpdateGetFromApiExtra.type = 'checkbox';
checkboxAdvancedDisableUpdateGetFromApiExtra.checked = settings.advancedDisableUpdateGetFromApiExtra;
checkboxAdvancedDisableUpdateGetFromApiExtra.addEventListener('change', () => {
try {
settings.advancedDisableUpdateGetFromApiExtra = checkboxAdvancedDisableUpdateGetFromApiExtra.checked;
if (settings.advancedDisableUpdateGetFromApiExtra) {
divLabelAdvancedIntervalGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelAdvancedIntervalGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelAdvancedDisableUpdateGetFromApiExtra.insertAdjacentElement('afterbegin', checkboxAdvancedDisableUpdateGetFromApiExtra);
const divLabelAdvancedIntervalGetFromApiExtra = document.createElement('div');
divLabelAdvancedIntervalGetFromApiExtra.classList.add('backup-div-third' + classAppendNewFreshSpace, 'backup-advanced');
divLabelAdvancedIntervalGetFromApiExtra.setAttribute('title',
'默认: 5天');
divControls.appendChild(divLabelAdvancedIntervalGetFromApiExtra);
const labelAdvancedIntervalGetFromApiExtra = document.createElement('label');
labelAdvancedIntervalGetFromApiExtra.classList.add('backup-label' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromApiExtra.appendChild(labelAdvancedIntervalGetFromApiExtra);
const inputTextAdvancedIntervalGetFromApiExtra = document.createElement('input');
inputTextAdvancedIntervalGetFromApiExtra.type = 'text';
inputTextAdvancedIntervalGetFromApiExtra.classList.add('backup-inputText' + classAppendNewFreshSpace);
inputTextAdvancedIntervalGetFromApiExtra.value = settings.advancedIntervalGetFromApiExtra;
inputTextAdvancedIntervalGetFromApiExtra.setAttribute('backup-def', 5);
inputTextAdvancedIntervalGetFromApiExtra.setAttribute('backup-min', 1);
inputTextAdvancedIntervalGetFromApiExtra.setAttribute('backup-max', 100);
inputTextAdvancedIntervalGetFromApiExtra.setAttribute('backup-setting', 'advancedIntervalGetFromApiExtra');
inputTextAdvancedIntervalGetFromApiExtra.addEventListener('blur', validateInputText);
labelAdvancedIntervalGetFromApiExtra.appendChild(document.createTextNode('最小更新间隔'))
labelAdvancedIntervalGetFromApiExtra.appendChild(inputTextAdvancedIntervalGetFromApiExtra);
labelAdvancedIntervalGetFromApiExtra.appendChild(document.createTextNode('天'));
const divLabelEnableGetFromBiliplus = document.createElement('div');
divLabelEnableGetFromBiliplus.classList.add('backup-div-second' + classAppendNewFreshSpace);
divLabelEnableGetFromBiliplus.setAttribute('title',
'默认: 开启\n' +
'地址: https://www.biliplus.com/video/{BV号}\n' +
'数据: 标题, 简介, 封面地址, UP主昵称, UP主头像地址, 视频发布动态内容, 每个分集的标题, 第1帧截图地址 (旧视频无法获取), cid (均为备份时的版本)\n' +
'部分视频BiliPlus无法备份, 可能的原因是其备份每个视频的信息较其他第三方网站更为丰富, 而某些信息从B站获取有一定的限制条件。');
divControls.appendChild(divLabelEnableGetFromBiliplus);
const labelEnableGetFromBiliplus = document.createElement('label');
labelEnableGetFromBiliplus.classList.add('backup-label' + classAppendNewFreshSpace);
labelEnableGetFromBiliplus.textContent = '从BiliPlus获取数据';
divLabelEnableGetFromBiliplus.appendChild(labelEnableGetFromBiliplus);
const checkboxEnableGetFromBiliplus = document.createElement('input');
checkboxEnableGetFromBiliplus.type = 'checkbox';
checkboxEnableGetFromBiliplus.checked = settings.enableGetFromBiliplus;
checkboxEnableGetFromBiliplus.addEventListener('change', () => {
try {
settings.enableGetFromBiliplus = checkboxEnableGetFromBiliplus.checked;
if (!settings.enableGetFromBiliplus) {
divLabelAdvancedDisableUpdateGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelAdvancedDisableUpdateGetFromBiliplus.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromBiliplus) {
divLabelAdvancedIntervalGetFromBiliplus.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableGetFromBiliplus.insertAdjacentElement('afterbegin', checkboxEnableGetFromBiliplus);
const divLabelAdvancedDisableUpdateGetFromBiliplus = document.createElement('div');
divLabelAdvancedDisableUpdateGetFromBiliplus.classList.add('backup-div-third' + classAppendNewFreshSpace, 'backup-advanced');
divLabelAdvancedDisableUpdateGetFromBiliplus.setAttribute('title',
'默认: 开启');
divControls.appendChild(divLabelAdvancedDisableUpdateGetFromBiliplus);
const labelAdvancedDisableUpdateGetFromBiliplus = document.createElement('label');
labelAdvancedDisableUpdateGetFromBiliplus.classList.add('backup-label' + classAppendNewFreshSpace);
labelAdvancedDisableUpdateGetFromBiliplus.textContent = '禁用更新';
divLabelAdvancedDisableUpdateGetFromBiliplus.appendChild(labelAdvancedDisableUpdateGetFromBiliplus);
const checkboxAdvancedDisableUpdateGetFromBiliplus = document.createElement('input');
checkboxAdvancedDisableUpdateGetFromBiliplus.type = 'checkbox';
checkboxAdvancedDisableUpdateGetFromBiliplus.checked = settings.advancedDisableUpdateGetFromBiliplus;
checkboxAdvancedDisableUpdateGetFromBiliplus.addEventListener('change', () => {
try {
settings.advancedDisableUpdateGetFromBiliplus = checkboxAdvancedDisableUpdateGetFromBiliplus.checked;
if (settings.advancedDisableUpdateGetFromBiliplus) {
divLabelAdvancedIntervalGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelAdvancedIntervalGetFromBiliplus.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelAdvancedDisableUpdateGetFromBiliplus.insertAdjacentElement('afterbegin', checkboxAdvancedDisableUpdateGetFromBiliplus);
const divLabelAdvancedIntervalGetFromBiliplus = document.createElement('div');
divLabelAdvancedIntervalGetFromBiliplus.classList.add('backup-div-third' + classAppendNewFreshSpace, 'backup-advanced');
divLabelAdvancedIntervalGetFromBiliplus.setAttribute('title',
'默认: 10星期');
divControls.appendChild(divLabelAdvancedIntervalGetFromBiliplus);
const labelAdvancedIntervalGetFromBiliplus = document.createElement('label');
labelAdvancedIntervalGetFromBiliplus.classList.add('backup-label' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromBiliplus.appendChild(labelAdvancedIntervalGetFromBiliplus);
const inputTextAdvancedIntervalGetFromBiliplus = document.createElement('input');
inputTextAdvancedIntervalGetFromBiliplus.type = 'text';
inputTextAdvancedIntervalGetFromBiliplus.classList.add('backup-inputText' + classAppendNewFreshSpace);
inputTextAdvancedIntervalGetFromBiliplus.value = settings.advancedIntervalGetFromBiliplus;
inputTextAdvancedIntervalGetFromBiliplus.setAttribute('backup-def', 10);
inputTextAdvancedIntervalGetFromBiliplus.setAttribute('backup-min', 1);
inputTextAdvancedIntervalGetFromBiliplus.setAttribute('backup-max', 100);
inputTextAdvancedIntervalGetFromBiliplus.setAttribute('backup-setting', 'advancedIntervalGetFromBiliplus');
inputTextAdvancedIntervalGetFromBiliplus.addEventListener('blur', validateInputText);
labelAdvancedIntervalGetFromBiliplus.appendChild(document.createTextNode('最小更新间隔'))
labelAdvancedIntervalGetFromBiliplus.appendChild(inputTextAdvancedIntervalGetFromBiliplus);
labelAdvancedIntervalGetFromBiliplus.appendChild(document.createTextNode('星期'));
const divLabelEnableGetFromJijidown = document.createElement('div');
divLabelEnableGetFromJijidown.classList.add('backup-div-second' + classAppendNewFreshSpace);
divLabelEnableGetFromJijidown.setAttribute('title',
'默认: 关闭\n' +
'唧唧的服务器尚不稳定, 从唧唧获取数据时可能会出现问题。\n' +
'地址: https://www.jijidown.com/api/v1/video_bv/get_info?id={BV号后10位}\n' +
'或 https://www.jiji.moe/api/v1/video_bv/get_info?id={BV号后10位} (取决于下面的单选项)\n' +
'数据: 标题, 简介, 封面地址, UP主昵称, UP主头像地址 (均为备份时的版本)');
divControls.appendChild(divLabelEnableGetFromJijidown);
const labelEnableGetFromJijidown = document.createElement('label');
labelEnableGetFromJijidown.classList.add('backup-label' + classAppendNewFreshSpace);
labelEnableGetFromJijidown.textContent = '从唧唧获取数据(不稳定)';
divLabelEnableGetFromJijidown.appendChild(labelEnableGetFromJijidown);
const checkboxEnableGetFromJijidown = document.createElement('input');
checkboxEnableGetFromJijidown.type = 'checkbox';
checkboxEnableGetFromJijidown.checked = settings.enableGetFromJijidown;
checkboxEnableGetFromJijidown.addEventListener('change', () => {
try {
settings.enableGetFromJijidown = checkboxEnableGetFromJijidown.checked;
if (!settings.enableGetFromJijidown) {
settings.enableGetFromJijidownExtra = false;
checkboxEnableGetFromJijidownExtra.checked = false;
divLabelAdvancedDisableUpdateGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL1.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL2.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelAdvancedDisableUpdateGetFromJijidown.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromJijidown) {
divLabelAdvancedIntervalGetFromJijidown.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divLabelEnableGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromJijidownExtra) {
divLabelAdvancedDisableUpdateGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromJijidownExtra) {
divLabelAdvancedIntervalGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
divSwitchGetFromJijidownURL1.classList.remove('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL2.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableGetFromJijidown.insertAdjacentElement('afterbegin', checkboxEnableGetFromJijidown);
const divLabelAdvancedDisableUpdateGetFromJijidown = document.createElement('div');
divLabelAdvancedDisableUpdateGetFromJijidown.classList.add('backup-div-third' + classAppendNewFreshSpace, 'backup-advanced');
divLabelAdvancedDisableUpdateGetFromJijidown.setAttribute('title',
'默认: 开启');
divControls.appendChild(divLabelAdvancedDisableUpdateGetFromJijidown);
const labelAdvancedDisableUpdateGetFromJijidown = document.createElement('label');
labelAdvancedDisableUpdateGetFromJijidown.classList.add('backup-label' + classAppendNewFreshSpace);
labelAdvancedDisableUpdateGetFromJijidown.textContent = '禁用更新';
divLabelAdvancedDisableUpdateGetFromJijidown.appendChild(labelAdvancedDisableUpdateGetFromJijidown);
const checkboxAdvancedDisableUpdateGetFromJijidown = document.createElement('input');
checkboxAdvancedDisableUpdateGetFromJijidown.type = 'checkbox';
checkboxAdvancedDisableUpdateGetFromJijidown.checked = settings.advancedDisableUpdateGetFromJijidown;
checkboxAdvancedDisableUpdateGetFromJijidown.addEventListener('change', () => {
try {
settings.advancedDisableUpdateGetFromJijidown = checkboxAdvancedDisableUpdateGetFromJijidown.checked;
if (settings.advancedDisableUpdateGetFromJijidown) {
divLabelAdvancedIntervalGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelAdvancedIntervalGetFromJijidown.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelAdvancedDisableUpdateGetFromJijidown.insertAdjacentElement('afterbegin', checkboxAdvancedDisableUpdateGetFromJijidown);
const divLabelAdvancedIntervalGetFromJijidown = document.createElement('div');
divLabelAdvancedIntervalGetFromJijidown.classList.add('backup-div-third' + classAppendNewFreshSpace, 'backup-advanced');
divLabelAdvancedIntervalGetFromJijidown.setAttribute('title',
'默认: 10星期');
divControls.appendChild(divLabelAdvancedIntervalGetFromJijidown);
const labelAdvancedIntervalGetFromJijidown = document.createElement('label');
labelAdvancedIntervalGetFromJijidown.classList.add('backup-label' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromJijidown.appendChild(labelAdvancedIntervalGetFromJijidown);
const inputTextAdvancedIntervalGetFromJijidown = document.createElement('input');
inputTextAdvancedIntervalGetFromJijidown.type = 'text';
inputTextAdvancedIntervalGetFromJijidown.classList.add('backup-inputText' + classAppendNewFreshSpace);
inputTextAdvancedIntervalGetFromJijidown.value = settings.advancedIntervalGetFromJijidown;
inputTextAdvancedIntervalGetFromJijidown.setAttribute('backup-def', 10);
inputTextAdvancedIntervalGetFromJijidown.setAttribute('backup-min', 1);
inputTextAdvancedIntervalGetFromJijidown.setAttribute('backup-max', 100);
inputTextAdvancedIntervalGetFromJijidown.setAttribute('backup-setting', 'advancedIntervalGetFromJijidown');
inputTextAdvancedIntervalGetFromJijidown.addEventListener('blur', validateInputText);
labelAdvancedIntervalGetFromJijidown.appendChild(document.createTextNode('最小更新间隔'))
labelAdvancedIntervalGetFromJijidown.appendChild(inputTextAdvancedIntervalGetFromJijidown);
labelAdvancedIntervalGetFromJijidown.appendChild(document.createTextNode('星期'));
const divLabelEnableGetFromJijidownExtra = document.createElement('div');
divLabelEnableGetFromJijidownExtra.classList.add('backup-div-second' + classAppendNewFreshSpace);
divLabelEnableGetFromJijidownExtra.setAttribute('title',
'默认: 关闭\n' +
'唧唧的服务器尚不稳定, 从唧唧获取数据时可能会出现问题。\n' +
'地址: https://www.jijidown.com/api/v1/video_bv/get_download_info?id={BV号后10位}\n' +
'或 https://www.jiji.moe/api/v1/video_bv/get_download_info?id={BV号后10位} (取决于下面的单选项)\n' +
'数据: 每个分集的标题, cid (均为备份时的版本)');
divControls.appendChild(divLabelEnableGetFromJijidownExtra);
const labelEnableGetFromJijidownExtra = document.createElement('label');
labelEnableGetFromJijidownExtra.classList.add('backup-label' + classAppendNewFreshSpace);
labelEnableGetFromJijidownExtra.textContent = '从唧唧获取额外数据(不稳定)';
divLabelEnableGetFromJijidownExtra.appendChild(labelEnableGetFromJijidownExtra);
const checkboxEnableGetFromJijidownExtra = document.createElement('input');
checkboxEnableGetFromJijidownExtra.type = 'checkbox';
checkboxEnableGetFromJijidownExtra.checked = settings.enableGetFromJijidownExtra;
checkboxEnableGetFromJijidownExtra.addEventListener('change', () => {
try {
settings.enableGetFromJijidownExtra = checkboxEnableGetFromJijidownExtra.checked;
if (!settings.enableGetFromJijidownExtra) {
divLabelAdvancedDisableUpdateGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelAdvancedDisableUpdateGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromJijidownExtra) {
divLabelAdvancedIntervalGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableGetFromJijidownExtra.insertAdjacentElement('afterbegin', checkboxEnableGetFromJijidownExtra);
const divLabelAdvancedDisableUpdateGetFromJijidownExtra = document.createElement('div');
divLabelAdvancedDisableUpdateGetFromJijidownExtra.classList.add('backup-div-third' + classAppendNewFreshSpace, 'backup-advanced');
divLabelAdvancedDisableUpdateGetFromJijidownExtra.setAttribute('title',
'默认: 开启');
divControls.appendChild(divLabelAdvancedDisableUpdateGetFromJijidownExtra);
const labelAdvancedDisableUpdateGetFromJijidownExtra = document.createElement('label');
labelAdvancedDisableUpdateGetFromJijidownExtra.classList.add('backup-label' + classAppendNewFreshSpace);
labelAdvancedDisableUpdateGetFromJijidownExtra.textContent = '禁用更新';
divLabelAdvancedDisableUpdateGetFromJijidownExtra.appendChild(labelAdvancedDisableUpdateGetFromJijidownExtra);
const checkboxAdvancedDisableUpdateGetFromJijidownExtra = document.createElement('input');
checkboxAdvancedDisableUpdateGetFromJijidownExtra.type = 'checkbox';
checkboxAdvancedDisableUpdateGetFromJijidownExtra.checked = settings.advancedDisableUpdateGetFromJijidownExtra;
checkboxAdvancedDisableUpdateGetFromJijidownExtra.addEventListener('change', () => {
try {
settings.advancedDisableUpdateGetFromJijidownExtra = checkboxAdvancedDisableUpdateGetFromJijidownExtra.checked;
if (settings.advancedDisableUpdateGetFromJijidownExtra) {
divLabelAdvancedIntervalGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelAdvancedIntervalGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelAdvancedDisableUpdateGetFromJijidownExtra.insertAdjacentElement('afterbegin', checkboxAdvancedDisableUpdateGetFromJijidownExtra);
const divLabelAdvancedIntervalGetFromJijidownExtra = document.createElement('div');
divLabelAdvancedIntervalGetFromJijidownExtra.classList.add('backup-div-third' + classAppendNewFreshSpace, 'backup-advanced');
divLabelAdvancedIntervalGetFromJijidownExtra.setAttribute('title',
'默认: 10星期');
divControls.appendChild(divLabelAdvancedIntervalGetFromJijidownExtra);
const labelAdvancedIntervalGetFromJijidownExtra = document.createElement('label');
labelAdvancedIntervalGetFromJijidownExtra.classList.add('backup-label' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromJijidownExtra.appendChild(labelAdvancedIntervalGetFromJijidownExtra);
const inputTextAdvancedIntervalGetFromJijidownExtra = document.createElement('input');
inputTextAdvancedIntervalGetFromJijidownExtra.type = 'text';
inputTextAdvancedIntervalGetFromJijidownExtra.classList.add('backup-inputText' + classAppendNewFreshSpace);
inputTextAdvancedIntervalGetFromJijidownExtra.value = settings.advancedIntervalGetFromJijidownExtra;
inputTextAdvancedIntervalGetFromJijidownExtra.setAttribute('backup-def', 10);
inputTextAdvancedIntervalGetFromJijidownExtra.setAttribute('backup-min', 1);
inputTextAdvancedIntervalGetFromJijidownExtra.setAttribute('backup-max', 100);
inputTextAdvancedIntervalGetFromJijidownExtra.setAttribute('backup-setting', 'advancedIntervalGetFromJijidownExtra');
inputTextAdvancedIntervalGetFromJijidownExtra.addEventListener('blur', validateInputText);
labelAdvancedIntervalGetFromJijidownExtra.appendChild(document.createTextNode('最小更新间隔'))
labelAdvancedIntervalGetFromJijidownExtra.appendChild(inputTextAdvancedIntervalGetFromJijidownExtra);
labelAdvancedIntervalGetFromJijidownExtra.appendChild(document.createTextNode('星期'));
const divSwitchGetFromJijidownURL1 = document.createElement('div');
divSwitchGetFromJijidownURL1.classList.add('backup-div-third' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL1.setAttribute('title',
'默认: www.jijidown.com\n' +
'www.jiji.moe为唧唧的新域名。\n' +
'如果脚本从唧唧获取数据时反复出现问题, 切换至另一域名可能有帮助。');
divControls.appendChild(divSwitchGetFromJijidownURL1);
const labelGetFromJijidownURL1 = document.createElement('label');
labelGetFromJijidownURL1.classList.add('backup-label' + classAppendNewFreshSpace);
labelGetFromJijidownURL1.textContent = 'www.jijidown.com';
divSwitchGetFromJijidownURL1.appendChild(labelGetFromJijidownURL1);
const radioGetFromJijidownURL1 = document.createElement('input');
radioGetFromJijidownURL1.type = 'radio';
radioGetFromJijidownURL1.name = 'getFromJijidownURL';
radioGetFromJijidownURL1.value = 'www.jijidown.com';
radioGetFromJijidownURL1.checked = settings.getFromJijidownURL === 'www.jijidown.com' ? true : false;
radioGetFromJijidownURL1.addEventListener('change', () => {
try {
settings.getFromJijidownURL = 'www.jijidown.com';
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelGetFromJijidownURL1.insertAdjacentElement('afterbegin', radioGetFromJijidownURL1);
const divSwitchGetFromJijidownURL2 = document.createElement('div');
divSwitchGetFromJijidownURL2.classList.add('backup-div-third' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL2.setAttribute('title',
'默认: www.jijidown.com\n' +
'www.jiji.moe为唧唧的新域名。\n' +
'如果脚本从唧唧获取数据时反复出现问题, 切换至另一域名可能有帮助。');
divControls.appendChild(divSwitchGetFromJijidownURL2);
const labelGetFromJijidownURL2 = document.createElement('label');
labelGetFromJijidownURL2.classList.add('backup-label' + classAppendNewFreshSpace);
labelGetFromJijidownURL2.textContent = 'www.jiji.moe';
divSwitchGetFromJijidownURL2.appendChild(labelGetFromJijidownURL2);
const radioGetFromJijidownURL2 = document.createElement('input');
radioGetFromJijidownURL2.type = 'radio';
radioGetFromJijidownURL2.name = 'getFromJijidownURL';
radioGetFromJijidownURL2.value = 'www.jiji.moe';
radioGetFromJijidownURL2.checked = settings.getFromJijidownURL === 'www.jiji.moe' ? true : false;
radioGetFromJijidownURL2.addEventListener('change', () => {
try {
settings.getFromJijidownURL = 'www.jiji.moe';
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelGetFromJijidownURL2.insertAdjacentElement('afterbegin', radioGetFromJijidownURL2);
const divLabelEnableGetFromXbeibeix = document.createElement('div');
divLabelEnableGetFromXbeibeix.classList.add('backup-div-second' + classAppendNewFreshSpace);
divLabelEnableGetFromXbeibeix.setAttribute('title',
'默认: 关闭\n' +
'贝贝工具站正在修改其网站页面, 从贝贝工具站获取数据时可能会出现问题。\n' +
'地址: https://xbeibeix.com/video/{BV号}\n' +
'或 https://bbdownloader.com/video/{BV号} (取决于下面的单选项)\n' +
'数据: 标题, 简介, 封面地址, UP主昵称 (均为备份时的版本)');
divControls.appendChild(divLabelEnableGetFromXbeibeix);
const labelEnableGetFromXbeibeix = document.createElement('label');
labelEnableGetFromXbeibeix.classList.add('backup-label' + classAppendNewFreshSpace);
labelEnableGetFromXbeibeix.textContent = '从贝贝工具站获取数据(不稳定)';
divLabelEnableGetFromXbeibeix.appendChild(labelEnableGetFromXbeibeix);
const checkboxEnableGetFromXbeibeix = document.createElement('input');
checkboxEnableGetFromXbeibeix.type = 'checkbox';
checkboxEnableGetFromXbeibeix.checked = settings.enableGetFromXbeibeix;
checkboxEnableGetFromXbeibeix.addEventListener('change', () => {
try {
settings.enableGetFromXbeibeix = checkboxEnableGetFromXbeibeix.checked;
GM_setValue('settings', settings);
if (!settings.enableGetFromXbeibeix) {
divLabelAdvancedDisableUpdateGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL1.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL2.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelAdvancedDisableUpdateGetFromXbeibeix.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!settings.advancedDisableUpdateGetFromXbeibeix) {
divLabelAdvancedIntervalGetFromXbeibeix.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divSwitchGetFromXbeibeixURL1.classList.remove('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL2.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
} catch (error) {
catchUnknownError(error);
}
});
labelEnableGetFromXbeibeix.insertAdjacentElement('afterbegin', checkboxEnableGetFromXbeibeix);
const divLabelAdvancedDisableUpdateGetFromXbeibeix = document.createElement('div');
divLabelAdvancedDisableUpdateGetFromXbeibeix.classList.add('backup-div-third' + classAppendNewFreshSpace, 'backup-advanced');
divLabelAdvancedDisableUpdateGetFromXbeibeix.setAttribute('title',
'默认: 开启');
divControls.appendChild(divLabelAdvancedDisableUpdateGetFromXbeibeix);
const labelAdvancedDisableUpdateGetFromXbeibeix = document.createElement('label');
labelAdvancedDisableUpdateGetFromXbeibeix.classList.add('backup-label' + classAppendNewFreshSpace);
labelAdvancedDisableUpdateGetFromXbeibeix.textContent = '禁用更新';
divLabelAdvancedDisableUpdateGetFromXbeibeix.appendChild(labelAdvancedDisableUpdateGetFromXbeibeix);
const checkboxAdvancedDisableUpdateGetFromXbeibeix = document.createElement('input');
checkboxAdvancedDisableUpdateGetFromXbeibeix.type = 'checkbox';
checkboxAdvancedDisableUpdateGetFromXbeibeix.checked = settings.advancedDisableUpdateGetFromXbeibeix;
checkboxAdvancedDisableUpdateGetFromXbeibeix.addEventListener('change', () => {
try {
settings.advancedDisableUpdateGetFromXbeibeix = checkboxAdvancedDisableUpdateGetFromXbeibeix.checked;
if (settings.advancedDisableUpdateGetFromXbeibeix) {
divLabelAdvancedIntervalGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelAdvancedIntervalGetFromXbeibeix.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelAdvancedDisableUpdateGetFromXbeibeix.insertAdjacentElement('afterbegin', checkboxAdvancedDisableUpdateGetFromXbeibeix);
const divLabelAdvancedIntervalGetFromXbeibeix = document.createElement('div');
divLabelAdvancedIntervalGetFromXbeibeix.classList.add('backup-div-third' + classAppendNewFreshSpace, 'backup-advanced');
divLabelAdvancedIntervalGetFromXbeibeix.setAttribute('title',
'默认: 10星期');
divControls.appendChild(divLabelAdvancedIntervalGetFromXbeibeix);
const labelAdvancedIntervalGetFromXbeibeix = document.createElement('label');
labelAdvancedIntervalGetFromXbeibeix.classList.add('backup-label' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromXbeibeix.appendChild(labelAdvancedIntervalGetFromXbeibeix);
const inputTextAdvancedIntervalGetFromXbeibeix = document.createElement('input');
inputTextAdvancedIntervalGetFromXbeibeix.type = 'text';
inputTextAdvancedIntervalGetFromXbeibeix.classList.add('backup-inputText' + classAppendNewFreshSpace);
inputTextAdvancedIntervalGetFromXbeibeix.value = settings.advancedIntervalGetFromXbeibeix;
inputTextAdvancedIntervalGetFromXbeibeix.setAttribute('backup-def', 10);
inputTextAdvancedIntervalGetFromXbeibeix.setAttribute('backup-min', 1);
inputTextAdvancedIntervalGetFromXbeibeix.setAttribute('backup-max', 100);
inputTextAdvancedIntervalGetFromXbeibeix.setAttribute('backup-setting', 'advancedIntervalGetFromXbeibeix');
inputTextAdvancedIntervalGetFromXbeibeix.addEventListener('blur', validateInputText);
labelAdvancedIntervalGetFromXbeibeix.appendChild(document.createTextNode('最小更新间隔'))
labelAdvancedIntervalGetFromXbeibeix.appendChild(inputTextAdvancedIntervalGetFromXbeibeix);
labelAdvancedIntervalGetFromXbeibeix.appendChild(document.createTextNode('星期'));
const divSwitchGetFromXbeibeixURL1 = document.createElement('div');
divSwitchGetFromXbeibeixURL1.classList.add('backup-div-third' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL1.setAttribute('title',
'默认: xbeibeix.com\n' +
'bbdownloader.com为贝贝工具站的新域名。\n' +
'如果脚本从贝贝工具站获取数据时反复出现问题, 切换至另一域名可能有帮助。');
divControls.appendChild(divSwitchGetFromXbeibeixURL1);
const labelGetFromXbeibeixURL1 = document.createElement('label');
labelGetFromXbeibeixURL1.classList.add('backup-label' + classAppendNewFreshSpace);
labelGetFromXbeibeixURL1.textContent = 'xbeibeix.com';
divSwitchGetFromXbeibeixURL1.appendChild(labelGetFromXbeibeixURL1);
const radioGetFromXbeibeixURL1 = document.createElement('input');
radioGetFromXbeibeixURL1.type = 'radio';
radioGetFromXbeibeixURL1.name = 'getFromXbeibeixURL';
radioGetFromXbeibeixURL1.value = 'xbeibeix.com';
radioGetFromXbeibeixURL1.checked = settings.getFromXbeibeixURL === 'xbeibeix.com' ? true : false;
radioGetFromXbeibeixURL1.addEventListener('change', () => {
try {
settings.getFromXbeibeixURL = 'xbeibeix.com';
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelGetFromXbeibeixURL1.insertAdjacentElement('afterbegin', radioGetFromXbeibeixURL1);
const divSwitchGetFromXbeibeixURL2 = document.createElement('div');
divSwitchGetFromXbeibeixURL2.classList.add('backup-div-third' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL2.setAttribute('title',
'默认: xbeibeix.com\n' +
'bbdownloader.com为贝贝工具站的新域名。\n' +
'如果脚本从贝贝工具站获取数据时反复出现问题, 切换至另一域名可能有帮助。');
divControls.appendChild(divSwitchGetFromXbeibeixURL2);
const labelGetFromXbeibeixURL2 = document.createElement('label');
labelGetFromXbeibeixURL2.classList.add('backup-label' + classAppendNewFreshSpace);
labelGetFromXbeibeixURL2.textContent = 'bbdownloader.com';
divSwitchGetFromXbeibeixURL2.appendChild(labelGetFromXbeibeixURL2);
const radioGetFromXbeibeixURL2 = document.createElement('input');
radioGetFromXbeibeixURL2.type = 'radio';
radioGetFromXbeibeixURL2.name = 'getFromXbeibeixURL';
radioGetFromXbeibeixURL2.value = 'bbdownloader.com';
radioGetFromXbeibeixURL2.checked = settings.getFromXbeibeixURL === 'bbdownloader.com' ? true : false;
radioGetFromXbeibeixURL2.addEventListener('change', () => {
try {
settings.getFromXbeibeixURL = 'bbdownloader.com';
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelGetFromXbeibeixURL2.insertAdjacentElement('afterbegin', radioGetFromXbeibeixURL2);
const divLabelEnableAutoNextPage = document.createElement('div');
divLabelEnableAutoNextPage.classList.add('backup-div-first' + classAppendNewFreshSpace);
divLabelEnableAutoNextPage.setAttribute('title',
'开启后脚本将在当前页的视频都处理完毕之后点击下一页, 继续处理下一页的视频。');
divControls.appendChild(divLabelEnableAutoNextPage);
const labelEnableAutoNextPage = document.createElement('label');
labelEnableAutoNextPage.classList.add('backup-label' + classAppendNewFreshSpace);
labelEnableAutoNextPage.textContent = '自动点击下一页';
divLabelEnableAutoNextPage.appendChild(labelEnableAutoNextPage);
const checkboxEnableAutoNextPage = document.createElement('input');
checkboxEnableAutoNextPage.type = 'checkbox';
checkboxEnableAutoNextPage.checked = enableAutoNextPage;
checkboxEnableAutoNextPage.addEventListener('change', async () => {
try {
enableAutoNextPage = checkboxEnableAutoNextPage.checked;
if (enableAutoNextPage && !activeControllers.size) {
if (newFreshSpace) {
const pager = Array.from(document.querySelectorAll('button.vui_pagenation--btn-side')).find(el => el.innerText === '下一页');
if (pager && !pager.classList.contains('vui_button--disabled')) {
await delay(500);
if (enableAutoNextPage) {
pager.click();
}
}
} else {
const pager = document.querySelector('li.be-pager-next');
if (pager && !pager.classList.contains('be-pager-disabled')) {
await delay(500);
if (enableAutoNextPage) {
pager.click();
}
}
}
}
} catch (error) {
catchUnknownError(error);
}
});
labelEnableAutoNextPage.insertAdjacentElement('afterbegin', checkboxEnableAutoNextPage);
const divLabelDisplayAdvancedControls = document.createElement('div');
divLabelDisplayAdvancedControls.classList.add('backup-div-first' + classAppendNewFreshSpace);
divControls.appendChild(divLabelDisplayAdvancedControls);
const labelDisplayAdvancedControls = document.createElement('label');
labelDisplayAdvancedControls.classList.add('backup-label' + classAppendNewFreshSpace);
// labelDisplayAdvancedControls.textContent = '显示高级选项和功能';
labelDisplayAdvancedControls.textContent = '显示高级选项';
divLabelDisplayAdvancedControls.appendChild(labelDisplayAdvancedControls);
const checkboxDisplayAdvancedControls = document.createElement('input');
checkboxDisplayAdvancedControls.type = 'checkbox';
checkboxDisplayAdvancedControls.checked = settings.displayAdvancedControls;
checkboxDisplayAdvancedControls.addEventListener('change', () => {
try {
settings.displayAdvancedControls = checkboxDisplayAdvancedControls.checked;
GM_setValue('settings', settings);
if (!settings.displayAdvancedControls) {
divControls.querySelectorAll('.backup-advanced').forEach(el => { el.classList.add('backup-hidden' + classAppendNewFreshSpace) });
} else {
divControls.querySelectorAll('.backup-advanced').forEach(el => { el.classList.remove('backup-hidden' + classAppendNewFreshSpace) });
}
} catch (error) {
catchUnknownError(error);
}
});
labelDisplayAdvancedControls.insertAdjacentElement('afterbegin', checkboxDisplayAdvancedControls);
const divButtonExportBackup = document.createElement('div');
divButtonExportBackup.classList.add('backup-div-first' + classAppendNewFreshSpace);
divButtonExportBackup.setAttribute('title',
'导入的备份数据会与脚本内已有的备份数据合并在一起。\n' +
'请不要随意修改导出的备份数据文件中的内容, 否则导入时可能会出错。');
divControls.appendChild(divButtonExportBackup);
const buttonExportBackup = document.createElement('button');
buttonExportBackup.type = 'button';
buttonExportBackup.classList.add('backup-button' + classAppendNewFreshSpace);
buttonExportBackup.textContent = '导出本地备份数据';
buttonExportBackup.addEventListener('click', () => {
try {
// const BVs = GM_listValues();
// const backupsToExport = {};
// BVs.forEach(BV => {
// backupsToExport[BV] = GM_getValue(BV, null);
// });
const backupsToExport = GM_getValues(GM_listValues().sort());
delete backupsToExport.settings;
// const backupData = JSON.stringify(backupToExport);
const backupsData = JSON.stringify(backupsToExport, null, 4);
const blob = new Blob([backupsData], { type: 'application/json' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = `${formatTsYYMMDD_HHMMSS(getCurrentTs())}.json`;
link.click();
URL.revokeObjectURL(link.href);
} catch (error) {
catchUnknownError(error);
}
});
divButtonExportBackup.appendChild(buttonExportBackup);
const divButtonImportBackup = document.createElement('div');
divButtonImportBackup.classList.add('backup-div-first' + classAppendNewFreshSpace);
divButtonImportBackup.setAttribute('title',
'导入的备份数据会与脚本内已有的备份数据合并在一起。\n' +
'请不要随意修改导出的备份数据文件中的内容, 否则导入时可能会出错。');
divControls.appendChild(divButtonImportBackup);
const buttonImportBackup = document.createElement('button');
buttonImportBackup.type = 'button';
buttonImportBackup.classList.add('backup-button' + classAppendNewFreshSpace);
buttonImportBackup.textContent = '导入本地备份数据';
divButtonImportBackup.appendChild(buttonImportBackup);
const divInputFile = document.createElement('div');
divInputFile.style.display = 'none';
divControls.appendChild(divInputFile);
const inputFile = document.createElement('input');
inputFile.type = 'file';
divInputFile.appendChild(inputFile);
buttonImportBackup.addEventListener('click', () => {
try {
inputFile.click();
} catch (error) {
catchUnknownError(error);
}
});
inputFile.addEventListener('change', (event) => {
try {
const file = event.target.files[0];
if (!file) {
return;
}
const reader = new FileReader();
reader.onload = (e) => {
try {
const backupsToImport = JSON.parse(e.target.result);
if (typeof backupsToImport !== 'object') {
addMessage('文件内容有误, 无法导入', false, true);
return;
}
for (const BVOfBackupToImport in backupsToImport) {
const backupToImport = backupsToImport[BVOfBackupToImport];
try {
///////////////////////////////////////////////////////////////////////////////////
// v9
if (backupToImport.timeFavorite) {
backupToImport.timeFavorite.forEach(el => {
if (typeof el.fid === 'string') {
el.fid = parseInt(el.fid, 10);
}
});
}
// v9
if (backupToImport.timeUpload && typeof backupToImport.timeUpload === 'object') {
if (backupToImport.timeUpload.length === 1) {
backupToImport.timeUpload = backupToImport.timeUpload[0].value;
} else {
backupToImport.timeUpload = null;
}
}
// v9
if (backupToImport.timePublish && typeof backupToImport.timePublish === 'object') {
if (backupToImport.timePublish.length === 1) {
backupToImport.timePublish = backupToImport.timePublish[0].value;
} else {
backupToImport.timePublish = null;
}
}
// v10
if (backupToImport.hasOwnProperty('jiji')) {
backupToImport.jijidown = backupToImport.jiji;
delete backupToImport.jiji;
}
// v10
if (backupToImport.hasOwnProperty('bbdownloader')) {
backupToImport.xbeibeix = backupToImport.bbdownloader;
delete backupToImport.bbdownloader;
}
// v12
['cover', 'upperAvatar'].forEach(key => {
if (backupToImport[key] && backupToImport[key].length > 1) {
const tempBackup = {};
backupToImport[key].forEach(el => {
updateArrayDataInBackup(tempBackup, key, el.value, el.ts, el.from);
});
backupToImport[key] = tempBackup[key];
}
});
// v14
if (backupToImport.hasOwnProperty('firstFrame')) {
delete backupToImport.firstFrame;
}
// v16
if (backupToImport.intro) {
const tempBackup = { intro: null };
backupToImport.intro.forEach(el => {
updateArrayDataInBackup(tempBackup, 'intro', el.value, el.ts, el.from);
});
backupToImport.intro = tempBackup.intro;
}
///////////////////////////////////////////////////////////////////////////////////
const backup = GM_getValue(backupToImport.BV, {
BV: null,
AV: null,
title: null,
intro: null,
cover: null,
upperUID: null,
upperName: null,
upperAvatar: null,
timeUpload: null,
timePublish: null,
timeFavorite: null,
dynamic: null,
pages: null,
api: null,
apiExtra: null,
biliplus: null,
jijidown: null,
jijidownExtra: null,
xbeibeix: null,
});
///////////////////////////////////////////////////////////////////////////////////
// v9
if (backup.timeFavorite) {
backup.timeFavorite.forEach(el => {
if (typeof el.fid === 'string') {
el.fid = parseInt(el.fid, 10);
}
});
}
// v9
if (backup.timeUpload && typeof backup.timeUpload === 'object') {
if (backup.timeUpload.length === 1) {
backup.timeUpload = backup.timeUpload[0].value;
} else {
backup.timeUpload = null;
}
}
// v9
if (backup.timePublish && typeof backup.timePublish === 'object') {
if (backup.timePublish.length === 1) {
backup.timePublish = backup.timePublish[0].value;
} else {
backup.timePublish = null;
}
}
// v10
if (backup.hasOwnProperty('jiji')) {
backup.jijidown = backup.jiji;
delete backup.jiji;
}
// v10
if (backup.hasOwnProperty('bbdownloader')) {
backup.xbeibeix = backup.bbdownloader;
delete backup.bbdownloader;
}
// v12
['cover', 'upperAvatar'].forEach(key => {
if (backup[key] && backup[key].length > 1) {
const tempBackup = {};
backup[key].forEach(el => {
updateArrayDataInBackup(tempBackup, key, el.value, el.ts, el.from);
});
backup[key] = tempBackup[key];
}
});
// v14
if (backup.hasOwnProperty('firstFrame')) {
delete backup.firstFrame;
}
// v16
if (backup.intro) {
const tempBackup = { intro: null };
backup.intro.forEach(el => {
updateArrayDataInBackup(tempBackup, 'intro', el.value, el.ts, el.from);
});
backup.intro = tempBackup.intro;
}
///////////////////////////////////////////////////////////////////////////////////
if (backupToImport.AV) {
backup.AV = backupToImport.AV;
}
if (backupToImport.BV) {
backup.BV = backupToImport.BV;
}
if (backupToImport.title) {
backupToImport.title.forEach(el => {
updateArrayDataInBackup(backup, 'title', el.value, el.ts, el.from);
});
}
if (backupToImport.intro) {
backupToImport.intro.forEach(el => {
updateArrayDataInBackup(backup, 'intro', el.value, el.ts, el.from);
});
}
if (backupToImport.cover) {
backupToImport.cover.forEach(el => {
updateArrayDataInBackup(backup, 'cover', el.value, el.ts, el.from);
});
}
if (backupToImport.upperUID) {
backup.upperUID = backupToImport.upperUID;
}
if (backupToImport.upperName) {
backupToImport.upperName.forEach(el => {
updateArrayDataInBackup(backup, 'upperName', el.value, el.ts, el.from);
});
}
if (backupToImport.upperAvatar) {
backupToImport.upperAvatar.forEach(el => {
updateArrayDataInBackup(backup, 'upperAvatar', el.value, el.ts, el.from);
});
}
if (backupToImport.timeUpload) {
backup.timeUpload = backupToImport.timeUpload;
}
if (backupToImport.timePublish) {
backup.timePublish = backupToImport.timePublish;
}
if (backupToImport.timeFavorite) {
backupToImport.timeFavorite.forEach(el => {
updateTimeFavoriteInBackup(backup, el.value, el.fid);
});
}
if (backupToImport.dynamic) {
backupToImport.dynamic.forEach(el => {
updateArrayDataInBackup(backup, 'dynamic', el.value, el.ts, el.from);
});
}
if (backupToImport.pages) {
backupToImport.pages.forEach(el => {
updatePagesInBackup(backup, el.index, el.title, el.firstFrame, el.cid, el.ts, el.from);
});
}
['api', 'apiExtra', 'biliplus', 'jijidown', 'jijidownExtra', 'xbeibeix'].forEach(key => {
if (backupToImport[key]) {
if (!backup[key]) {
backup[key] = { value: backupToImport[key].value, ts: backupToImport[key].ts };
} else {
if (backup[key].ts < backupToImport[key].ts) {
backup[key].value = backupToImport[key].value;
backup[key].ts = backupToImport[key].ts;
}
}
}
});
const sortedBackup = {};
for (const sortedKey of sortedKeys) {
sortedBackup[sortedKey] = backup[sortedKey];
}
GM_setValue(backupToImport.BV, sortedBackup);
} catch (error) {
addMessage('导入该视频失败', false, true);
if (backupToImport.BV) {
addMessage(`BV号: ${backupToImport.BV}`, true);
}
if (error instanceof Error) {
addMessage(error.stack, true);
console.error(error);
} else {
addMessage(error[0], true);
for (let i = 1; i < error.length; i++) {
addMessage(error[i], true);
}
}
console.error('需要导入的数据');
console.error(backupToImport);
if (backupToImport.BV) {
console.error('本地已有的数据');
console.error(GM_getValue(backupToImport.BV, {}));
}
}
}
addMessage('导入完成');
} catch (error) {
catchUnknownError(error);
}
};
reader.readAsText(file);
} catch (error) {
catchUnknownError(error);
}
});
const divButtonStopProcessing = document.createElement('div');
divButtonStopProcessing.classList.add('backup-div-first' + classAppendNewFreshSpace);
divButtonStopProcessing.setAttribute('title',
'此功能适用于脚本处理视频时反复出现问题的情况。');
divControls.appendChild(divButtonStopProcessing);
const buttonStopProcessing = document.createElement('button');
buttonStopProcessing.type = 'button';
buttonStopProcessing.classList.add('backup-button' + classAppendNewFreshSpace);
buttonStopProcessing.textContent = '停止处理当前页视频';
buttonStopProcessing.addEventListener('click', () => {
try {
abortActiveControllers();
} catch (error) {
catchUnknownError(error);
}
});
divButtonStopProcessing.appendChild(buttonStopProcessing);
if (enableDebug) {
const divButton = document.createElement('div');
divButton.classList.add('backup-div-first' + classAppendNewFreshSpace, 'backup-advanced');
divControls.appendChild(divButton);
const button = document.createElement('button');
button.type = 'button';
button.classList.add('backup-button' + classAppendNewFreshSpace);
button.textContent = '清空提示信息';
button.addEventListener('click', () => {
try {
clearMessage();
} catch (error) {
catchUnknownError(error);
}
});
divButton.appendChild(button);
}
if (enableDebug) {
const divButton = document.createElement('div');
divButton.classList.add('backup-div-first' + classAppendNewFreshSpace, 'backup-advanced');
divControls.appendChild(divButton);
const button = document.createElement('button');
button.type = 'button';
button.classList.add('backup-button' + classAppendNewFreshSpace);
button.textContent = '添加提示信息';
button.addEventListener('click', () => {
try {
addMessage(divMessage.scrollHeight);
} catch (error) {
catchUnknownError(error);
}
});
divButton.appendChild(button);
}
divMessage = document.createElement('div');
divMessage.classList.add('backup-divMessage' + classAppendNewFreshSpace);
divControls.appendChild(divMessage);
if (displayUpdate) {
setTimeout(() => {
addMessage(updates);
}, 300);
}
if (!settings.processNormal && !settings.processDisabled) {
divLabelEnableGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL1.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL2.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL1.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL2.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
if (!settings.enableGetFromApi) {
divLabelAdvancedDisableUpdateGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
if (settings.advancedDisableUpdateGetFromApi) {
divLabelAdvancedIntervalGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
}
if (!settings.enableGetFromApiExtra) {
divLabelAdvancedDisableUpdateGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
if (settings.advancedDisableUpdateGetFromApiExtra) {
divLabelAdvancedIntervalGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
}
}
}
if (!settings.enableGetFromBiliplus) {
divLabelAdvancedDisableUpdateGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
if (settings.advancedDisableUpdateGetFromBiliplus) {
divLabelAdvancedIntervalGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
}
}
if (!settings.enableGetFromJijidown) {
divLabelAdvancedDisableUpdateGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedDisableUpdateGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL1.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL2.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
if (settings.advancedDisableUpdateGetFromJijidown) {
divLabelAdvancedIntervalGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
}
if (!settings.enableGetFromJijidownExtra) {
divLabelAdvancedDisableUpdateGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
if (settings.advancedDisableUpdateGetFromJijidownExtra) {
divLabelAdvancedIntervalGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
}
}
}
if (!settings.enableGetFromXbeibeix) {
divLabelAdvancedDisableUpdateGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelAdvancedIntervalGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL1.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL2.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
if (settings.advancedDisableUpdateGetFromXbeibeix) {
divLabelAdvancedIntervalGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
}
}
}
if (!settings.displayAdvancedControls) {
divControls.querySelectorAll('.backup-advanced').forEach(el => {
el.classList.add('backup-hidden' + classAppendNewFreshSpace);
});
}
}
function appendDropdowns(dropdownContainer, BV) {
try {
if (newFreshSpace) {
const biliCardDropdownVisible = document.querySelectorAll('div.bili-card-dropdown--visible');
if (biliCardDropdownVisible.length !== 1) {
addMessage('下拉列表开关不存在或不唯一, 无法确定下拉列表所对应的视频, 刷新页面可能有帮助', false, true);
return;
}
let divTargetVideo;
try {
divTargetVideo = document.querySelector('div.items__item:has(div.bili-card-dropdown--visible)');
} catch {
const items = document.querySelectorAll('div.items__item');
for (const item of items) {
if (item.contains(biliCardDropdownVisible[0])) {
divTargetVideo = item;
break;
}
}
}
if (!divTargetVideo) {
addMessage('无法确定下拉列表所对应的视频, 请反馈该问题', false, true);
return;
}
if (divTargetVideo.querySelector('div.bili-cover-card__tags')) {
if (enableDebug) console.log('不处理特殊视频');
return;
}
if (!settings.processNormal && divTargetVideo.querySelector('div.bili-cover-card__stats')) {
return;
}
if (!settings.processDisabled && !divTargetVideo.querySelector('div.bili-cover-card__stats')) {
return;
}
const getBVFromURLMatch = biliCardDropdownVisible[0].parentNode.querySelector('a').getAttribute('href').match(getBVFromURLRegex);
if (!getBVFromURLMatch) {
addMessage('无法获取该视频的BV号, 请检查是否有其他脚本或插件修改了该视频封面和标题的链接地址, 并将其关闭', false, true);
return;
}
BV = getBVFromURLMatch[1];
} else {
if (dropdownContainer.lastElementChild.classList.contains('backup')) {
return;
}
dropdownContainer.lastElementChild.classList.add('be-dropdown-item-delimiter');
}
const backup = GM_getValue(BV, {});
if (backup.cover) {
const dropdownCover = document.createElement(newFreshSpace ? 'div' : 'li');
dropdownCover.classList.add(newFreshSpace ? 'bili-card-dropdown-popper__item' : 'be-dropdown-item');
if (!newFreshSpace) {
dropdownCover.classList.add('backup');
}
dropdownCover.setAttribute('title',
'查看该视频的本地备份数据中所有版本的封面原图, 从新到旧');
dropdownCover.textContent = '封面原图';
dropdownCover.addEventListener('click', () => {
try {
if (newFreshSpace) {
dropdownContainer.classList.remove('visible');
}
GM_openInTab(`https://${backup.cover[backup.cover.length - 1].value}`, { active: true, insert: true, setParent: true });
for (let i = backup.cover.length - 2; i >= 0; i--) {
GM_openInTab(`https://${backup.cover[i].value}`, { insert: false, setParent: true });
}
} catch (error) {
catchUnknownError(error);
}
});
dropdownContainer.appendChild(dropdownCover);
}
const dropdownLocal = document.createElement(newFreshSpace ? 'div' : 'li');
dropdownLocal.classList.add(newFreshSpace ? 'bili-card-dropdown-popper__item' : 'be-dropdown-item');
if (!newFreshSpace) {
dropdownLocal.classList.add('backup');
}
dropdownLocal.setAttribute('title',
'查看该视频的本地备份数据');
dropdownLocal.textContent = '本地备份数据';
dropdownLocal.addEventListener('click', () => {
try {
if (newFreshSpace) {
dropdownContainer.classList.remove('visible');
}
const data = GM_getValue(BV, {});
const json = JSON.stringify(data);
// GM_openInTab('data:text/plain;charset=utf-8,' + encodeURIComponent(json), { active: true, insert: false, setParent: true });
GM_openInTab('data:application/json;charset=utf-8,' + encodeURIComponent(json), { active: true, insert: false, setParent: true });
} catch (error) {
catchUnknownError(error);
}
});
dropdownContainer.appendChild(dropdownLocal);
const dropdownJump = document.createElement(newFreshSpace ? 'div' : 'li');
dropdownJump.classList.add(newFreshSpace ? 'bili-card-dropdown-popper__item' : 'be-dropdown-item');
if (!newFreshSpace) {
dropdownJump.classList.add('backup');
}
dropdownJump.setAttribute('title',
'跳转至该视频在各个第三方网站的原始页面');
dropdownJump.textContent = '跳转至BJX';
dropdownJump.addEventListener('click', () => {
try {
if (newFreshSpace) {
dropdownContainer.classList.remove('visible');
}
GM_openInTab(`https://www.biliplus.com/video/${BV}`, { active: true, insert: false, setParent: true });
GM_openInTab(`https://${settings.getFromJijidownURL}/video/${BV}`, { insert: false, setParent: true });
GM_openInTab(`https://${settings.getFromXbeibeixURL}/video/${BV}`, { insert: false, setParent: true });
} catch (error) {
catchUnknownError(error);
}
});
dropdownContainer.appendChild(dropdownJump);
const dropdownReset = document.createElement(newFreshSpace ? 'div' : 'li');
dropdownReset.classList.add(newFreshSpace ? 'bili-card-dropdown-popper__item' : 'be-dropdown-item');
if (!newFreshSpace) {
dropdownReset.classList.add('backup');
}
dropdownReset.setAttribute('title',
'如果该视频的本地备份数据出现错乱, 请使用此功能将其删除以便重新备份该视频。\n' +
'如果您想删除脚本内所有已保存的数据, 请依次点击: Tampermonkey > 管理面板 >\n' +
'哔哩哔哩(B站|Bilibili)收藏夹Fix (备份视频信息) > 开发者 > 重置到出厂。');
dropdownReset.textContent = '重置备份数据';
dropdownReset.addEventListener('click', () => {
try {
if (newFreshSpace) {
dropdownContainer.classList.remove('visible');
}
GM_deleteValue(BV);
} catch (error) {
catchUnknownError(error);
}
});
dropdownContainer.appendChild(dropdownReset);
} catch (error) {
catchUnknownError(error);
}
}
async function getFromApi(AVBVTitle, backup, spanA, apiDetails, fid, pageNumber, disabled, spanFavTime) {
if (!apiDetails.value) {
const response = await new Promise(async (resolve, reject) => {
GM.xmlHttpRequest({
method: 'GET',
url: await appendParamsForGetFromApi(fid, pageNumber, pageSize),
timeout: 5000,
responseType: 'json',
onload: (res) => resolve(res),
onerror: (res) => reject(['请求失败', 'api.bilibili.com/x/v3/fav/resource/list', res.error]),
ontimeout: () => reject(['请求超时', 'api.bilibili.com/x/v3/fav/resource/list'])
});
});
apiDetails.value = response.response.data.medias;
}
const apiDetail = apiDetails.value.find(el => el.bvid === AVBVTitle.BV);
if (!apiDetail) {
if (enableDebug) console.warn('getFromApi 从B站接口获取的数据中没有该视频');
return true;
}
if (!AVBVTitle.AV) {
AVBVTitle.AV = apiDetail.id;
backup.AV = apiDetail.id;
}
if (enableDebug) console.log('从B站接口获取数据');
if (enableDebug) consoleAVBVTitle('debug', AVBVTitle);
if (enableDebug) console.debug(apiDetail);
if (!disabled) {
updateArrayDataInBackup(backup, 'title', apiDetail.title, getCurrentTs(), 'api.bilibili.com/x/v3/fav/resource/list');
updateArrayDataInBackup(backup, 'cover', apiDetail.cover, getCurrentTs(), 'api.bilibili.com/x/v3/fav/resource/list');
}
updateArrayDataInBackup(backup, 'intro', apiDetail.intro, getCurrentTs(), 'api.bilibili.com/x/v3/fav/resource/list');
if (!disabled && apiDetail.intro.length >= 255) {
if (settings.enableGetFromApiExtra && (!backup.apiExtra || (!settings.advancedDisableUpdateGetFromApiExtra && getCurrentTs() - backup.apiExtra.ts > 3600 * 24 * settings.advancedIntervalGetFromApiExtra))) {
} else {
const response = await new Promise((resolve, reject) => {
GM.xmlHttpRequest({
method: 'GET',
url: `https://api.bilibili.com/x/web-interface/archive/desc?bvid=${AVBVTitle.BV}`,
timeout: 5000,
responseType: 'json',
onload: (res) => resolve(res),
onerror: (res) => reject(['请求失败', 'api.bilibili.com/x/web-interface/archive/desc', res.error]),
ontimeout: () => reject(['请求超时', 'api.bilibili.com/x/web-interface/archive/desc'])
});
});
updateArrayDataInBackup(backup, 'intro', response.response.data, getCurrentTs(), 'api.bilibili.com/x/web-interface/archive/desc');
}
}
if (!backup.upperUID) {
backup.upperUID = apiDetail.upper.mid;
}
updateArrayDataInBackup(backup, 'upperName', apiDetail.upper.name, getCurrentTs(), 'api.bilibili.com/x/v3/fav/resource/list');
updateArrayDataInBackup(backup, 'upperAvatar', apiDetail.upper.face, getCurrentTs(), 'api.bilibili.com/x/v3/fav/resource/list');
backup.timeUpload = apiDetail.ctime;
backup.timePublish = apiDetail.pubtime;
updateTimeFavoriteInBackup(backup, apiDetail.fav_time, fid);
if (newFreshSpace) {
spanFavTime.textContent = `投稿于:${formatTsTimePublish(apiDetail.pubtime * 1000)}`;
spanFavTime.setAttribute('title', new Date(apiDetail.pubtime * 1000).toLocaleString());
} else {
spanFavTime.textContent = `收藏于:${formatTsTimeFavorite(new Date(apiDetail.fav_time * 1000))}`;
spanFavTime.setAttribute('title', new Date(apiDetail.fav_time * 1000).toLocaleString());
}
if (disabled) {
backup.api = { value: false, ts: getCurrentTs() };
spanA.style.color = '#ff0000';
} else {
backup.api = { value: true, ts: getCurrentTs() };
spanA.style.color = '#00ff00';
}
const sortedBackup = {};
for (const sortedKey of sortedKeys) {
sortedBackup[sortedKey] = backup[sortedKey];
}
GM_setValue(AVBVTitle.BV, sortedBackup);
if (enableDebug) console.log('保存B站接口的数据至本地');
if (enableDebug) consoleAVBVTitle('debug', AVBVTitle);
if (enableDebug) console.debug(sortedBackup);
}
async function getFromApiExtra(AVBVTitle, backup, spanA, disabled) {
if (disabled) {
backup.apiExtra = { value: false, ts: getCurrentTs() };
spanA.style.color = '#800000';
} else {
const response = await new Promise((resolve, reject) => {
GM.xmlHttpRequest({
method: 'GET',
url: `https://api.bilibili.com/x/web-interface/view?bvid=${AVBVTitle.BV}`,
timeout: 5000,
responseType: 'json',
onload: (res) => resolve(res),
onerror: (res) => reject(['请求失败', 'api.bilibili.com/x/web-interface/view', res.error]),
ontimeout: () => reject(['请求超时', 'api.bilibili.com/x/web-interface/view'])
});
});
updateArrayDataInBackup(backup, 'intro', response.response.data.desc, getCurrentTs(), 'api.bilibili.com/x/web-interface/view');
if (response.response.data.desc_v2) {
let introWithUID = '';
for (const [index, desc] of response.response.data.desc_v2.entries()) {
if (desc.type === 1) {
introWithUID = introWithUID + desc.raw_text;
} else if (desc.type === 2) {
introWithUID = introWithUID + `@${desc.raw_text}{{UID:${desc.biz_id}}}` + (index === response.response.data.desc_v2.length - 1 ? '' : ' ');
} else {
if (enableDebug) console.warn(`getFromApiExtra desc_v2未知type: ${desc.type}`);
}
}
updateArrayDataInBackup(backup, 'intro', introWithUID, getCurrentTs(), 'api.bilibili.com/x/web-interface/view');
}
updateArrayDataInBackup(backup, 'dynamic', response.response.data.dynamic, getCurrentTs(), 'api.bilibili.com/x/web-interface/view');
response.response.data.pages.forEach(el => {
updatePagesInBackup(backup, el.page, el.part, el.first_frame, el.cid, getCurrentTs(), 'api.bilibili.com/x/web-interface/view');
});
backup.apiExtra = { value: true, ts: getCurrentTs() };
spanA.style.color = '#008000';
}
const sortedBackup = {};
for (const sortedKey of sortedKeys) {
sortedBackup[sortedKey] = backup[sortedKey];
}
GM_setValue(AVBVTitle.BV, sortedBackup);
if (enableDebug) console.log('保存B站接口的额外数据至本地');
if (enableDebug) consoleAVBVTitle('debug', AVBVTitle);
if (enableDebug) console.debug(sortedBackup);
}
async function getFromBiliplus(AVBVTitle, backup, spanB) {
const response = await new Promise((resolve, reject) => {
GM.xmlHttpRequest({
method: 'GET',
url: `https://www.biliplus.com/video/${AVBVTitle.BV}`,
timeout: 5000,
onload: (res) => resolve(res),
onerror: (res) => reject(['请求失败', 'www.biliplus.com/video', res.error]),
ontimeout: () => reject(['请求超时', 'www.biliplus.com/video'])
});
});
const json = JSON.parse(response.response.match(getJsonFromBiliplusRegex)[1]);
if (json.title) {
if (enableDebug) console.log('从BiliPlus获取有效数据');
if (enableDebug) consoleAVBVTitle('debug', AVBVTitle);
if (enableDebug) console.debug(json);
if (!json.lastupdatets) {
if (!json.lastupdate) {
throw ['从BiliPlus获取的数据中无备份时间, 请反馈该问题'];
}
if (!localeTimeStringRegex.test(json.lastupdate)) {
throw ['从BiliPlus获取的数据中备份时间不符合规范, 请反馈该问题'];
}
if (isNaN(new Date(json.lastupdate).getTime())) {
throw ['从BiliPlus获取的数据中备份时间不符合规范, 请反馈该问题'];
}
json.lastupdatets = new Date(json.lastupdate).getTime() / 1000;
}
updateArrayDataInBackup(backup, 'title', json.title, json.lastupdatets, 'www.biliplus.com/video');
updateArrayDataInBackup(backup, 'intro', json.description, json.lastupdatets, 'www.biliplus.com/video');
updateArrayDataInBackup(backup, 'cover', json.pic, json.lastupdatets, 'www.biliplus.com/video');
updateArrayDataInBackup(backup, 'upperName', json.author, json.lastupdatets, 'www.biliplus.com/video');
json.list.forEach(el => {
updatePagesInBackup(backup, el.page, el.part, el.first_frame, el.cid, json.lastupdatets, 'www.biliplus.com/video');
});
if (json.v2_app_api) {
updateArrayDataInBackup(backup, 'title', json.v2_app_api.title, json.lastupdatets, 'www.biliplus.com/video');
updateArrayDataInBackup(backup, 'intro', json.v2_app_api.desc, json.lastupdatets, 'www.biliplus.com/video');
updateArrayDataInBackup(backup, 'cover', json.v2_app_api.pic, json.lastupdatets, 'www.biliplus.com/video');
updateArrayDataInBackup(backup, 'upperName', json.v2_app_api.owner.name, json.lastupdatets, 'www.biliplus.com/video');
updateArrayDataInBackup(backup, 'upperAvatar', json.v2_app_api.owner.face, json.lastupdatets, 'www.biliplus.com/video');
///////////////////////////////////////////////////////////////////////////////////
// if (json.v2_app_api.cid && json.v2_app_api.cid !== json.list[0].cid) {
// console.error(json.v2_app_api.cid);
// console.error(json.list[0].cid);
// console.error('getFromBiliplus cid 不一致1');
// }
// if (json.v2_app_api.cid && json.v2_app_api.cid !== json.v2_app_api.pages[0].cid) {
// console.error(json.v2_app_api.cid);
// console.error(json.v2_app_api.pages[0].cid);
// console.error('getFromBiliplus cid 不一致2');
// }
// if (json.list[0].cid !== json.v2_app_api.pages[0].cid) {
// console.error(json.list[0].cid);
// console.error(json.v2_app_api.pages[0].cid);
// console.error('getFromBiliplus cid 不一致3');
// }
///////////////////////////////////////////////////////////////////////////////////
if (json.v2_app_api.first_frame !== json.v2_app_api.pages[0].first_frame) {
if (enableDebug) console.warn('getFromBiliplus firstFrame 不一致');
if (enableDebug) console.warn(json.v2_app_api.first_frame);
if (enableDebug) console.warn(json.v2_app_api.pages[0].first_frame);
updatePagesInBackup(backup, 0, undefined, json.v2_app_api.first_frame, 0, json.lastupdatets, 'www.biliplus.com/video');
}
updateArrayDataInBackup(backup, 'dynamic', json.v2_app_api.dynamic, json.lastupdatets, 'www.biliplus.com/video');
json.v2_app_api.pages.forEach(el => {
updatePagesInBackup(backup, el.page, el.part, el.first_frame, el.cid, json.lastupdatets, 'www.biliplus.com/video');
});
}
backup.biliplus = { value: true, ts: getCurrentTs() };
spanB.style.color = '#00ff00';
} else {
if (enableDebug) console.log('从BiliPlus获取无效数据');
if (enableDebug) consoleAVBVTitle('debug', AVBVTitle);
if (enableDebug) console.debug(json);
backup.biliplus = { value: false, ts: getCurrentTs() };
spanB.style.color = '#ff0000';
}
}
async function getFromJijidown(AVBVTitle, backup, spanJ) {
let retryCount = 0;
while (true) {
const response = await new Promise((resolve, reject) => {
GM.xmlHttpRequest({
method: 'GET',
url: `https://${settings.getFromJijidownURL}/api/v1/video_bv/get_info?id=${AVBVTitle.BV.slice(2)}`,
timeout: 5000,
responseType: 'json',
onload: (res) => resolve(res),
onerror: (res) => reject(['请求失败', `${settings.getFromJijidownURL}/api/v1/video_bv/get_info`, res.error]),
ontimeout: () => reject(['请求超时', `${settings.getFromJijidownURL}/api/v1/video_bv/get_info`])
});
});
if (enableDebug) console.debug(response);
if (response.status !== 200) {
throw ['请求失败', `${settings.getFromJijidownURL}/api/v1/video_bv/get_info`, `${response.status} ${response.statusText}`];
}
if (response.response.upid > 0) {
if (enableDebug) console.log('从唧唧获取有效数据');
if (enableDebug) consoleAVBVTitle('debug', AVBVTitle);
if (enableDebug) console.debug(response.response);
updateArrayDataInBackup(backup, 'title', response.response.title, response.response.ltime, `${settings.getFromJijidownURL}/api/v1/video_bv/get_info`);
if (response.response.desc) {
updateArrayDataInBackup(backup, 'intro', decodeHTMLEntities(response.response.desc.replaceAll('<br/>', '\n').replaceAll('\r', '\\r')).replaceAll('\\r', '\r'), response.response.ltime, `${settings.getFromJijidownURL}/api/v1/video_bv/get_info`);
}
updateArrayDataInBackup(backup, 'cover', response.response.img, response.response.ltime, `${settings.getFromJijidownURL}/api/v1/video_bv/get_info`);
if (response.response.up.id > 0) {
updateArrayDataInBackup(backup, 'upperName', response.response.up.author, response.response.ltime, `${settings.getFromJijidownURL}/api/v1/video_bv/get_info`);
updateArrayDataInBackup(backup, 'upperAvatar', response.response.up.avatar, response.response.ltime, `${settings.getFromJijidownURL}/api/v1/video_bv/get_info`);
}
backup.jijidown = { value: true, ts: getCurrentTs() };
spanJ.style.color = '#00ff00';
if (settings.enableGetFromJijidownExtra && (!backup.jijidownExtra || (!settings.advancedDisableUpdateGetFromJijidownExtra && getCurrentTs() - backup.jijidownExtra.ts > 3600 * 24 * 7 * settings.advancedIntervalGetFromJijidownExtra))) {
await getFromJijidownExtra(AVBVTitle, backup, spanJ, response.response.ltime);
}
return;
} else if (response.response.msg === 'loading') {
retryCount++;
if (enableDebug) console.log('从唧唧获取无效数据');
if (enableDebug) consoleAVBVTitle('debug', AVBVTitle);
if (enableDebug) console.log(`请求重试次数: ${retryCount}`);
if (enableDebug) console.debug(response.response);
if (retryCount > 4) {
throw ['请求重试次数过多', `${settings.getFromJijidownURL}/api/v1/video_bv/get_info`];
}
} else {
if (enableDebug) console.log('从唧唧获取无效数据');
if (enableDebug) consoleAVBVTitle('debug', AVBVTitle);
if (enableDebug) console.debug(response.response);
backup.jijidown = { value: false, ts: getCurrentTs() };
if (settings.enableGetFromJijidownExtra && (!backup.jijidownExtra || (!settings.advancedDisableUpdateGetFromJijidownExtra && getCurrentTs() - backup.jijidownExtra.ts > 3600 * 24 * 7 * settings.advancedIntervalGetFromJijidownExtra))) {
backup.jijidownExtra = { value: false, ts: getCurrentTs() };
spanJ.style.color = '#800000';
} else {
spanJ.style.color = '#ff0000';
}
return;
}
await delay(600);
}
}
async function getFromJijidownExtra(AVBVTitle, backup, spanJ, ts) {
const response = await new Promise((resolve, reject) => {
GM.xmlHttpRequest({
method: 'GET',
url: `https://${settings.getFromJijidownURL}/api/v1/video_bv/get_download_info?id=${AVBVTitle.BV.slice(2)}`,
timeout: 5000,
responseType: 'json',
onload: (res) => resolve(res),
onerror: (res) => reject(['请求失败', `${settings.getFromJijidownURL}/api/v1/video_bv/get_download_info`, res.error]),
ontimeout: () => reject(['请求超时', `${settings.getFromJijidownURL}/api/v1/video_bv/get_download_info`])
});
});
if (enableDebug) console.debug(response);
if (response.status !== 200) {
throw ['请求失败', `${settings.getFromJijidownURL}/api/v1/video_bv/get_download_info`, `${response.status} ${response.statusText}`];
}
if (response.response.res && response.response.res.length) {
if (enableDebug) console.log('从唧唧获取有效额外数据');
if (enableDebug) consoleAVBVTitle('debug', AVBVTitle);
if (enableDebug) console.debug(response.response);
response.response.res.forEach(el => {
updatePagesInBackup(backup, 0, el.part, undefined, el.cid, ts, `${settings.getFromJijidownURL}/api/v1/video_bv/get_download_info`);
});
backup.jijidownExtra = { value: true, ts: getCurrentTs() };
spanJ.style.color = '#008000';
} else {
if (enableDebug) console.log('从唧唧获取无效额外数据');
if (enableDebug) consoleAVBVTitle('debug', AVBVTitle);
if (enableDebug) console.debug(response.response);
backup.jijidownExtra = { value: false, ts: getCurrentTs() };
spanJ.style.color = '#800000';
}
}
async function getFromXbeibeix(AVBVTitle, backup, spanX) {
const response = await new Promise((resolve, reject) => {
GM.xmlHttpRequest({
method: 'GET',
url: `https://${settings.getFromXbeibeixURL}/video/${AVBVTitle.BV}`,
timeout: 5000,
onload: (res) => resolve(res),
onerror: (res) => reject(['请求失败', `${settings.getFromXbeibeixURL}/video`, res.error]),
ontimeout: () => reject(['请求超时', `${settings.getFromXbeibeixURL}/video`])
});
});
if (enableDebug) console.debug(response);
if (response.status !== 200) {
throw ['请求失败', `${settings.getFromXbeibeixURL}/video`, `${response.status} ${response.statusText}`];
}
if (response.finalUrl !== `https://${settings.getFromXbeibeixURL}/`) {
if (enableDebug) console.log('从贝贝工具站获取有效数据');
if (enableDebug) consoleAVBVTitle('debug', AVBVTitle);
if (enableDebug) console.debug(response);
updateArrayDataInBackup(backup, 'title', response.responseXML.querySelector('h5.fw-bold').innerText, undefined, `${settings.getFromXbeibeixURL}/video`);
if (response.responseXML.querySelector('div.col-8 > textarea').innerText) {
updateArrayDataInBackup(backup, 'intro', decodeHTMLEntities(response.responseXML.querySelector('div.col-8 > textarea').innerText), undefined, `${settings.getFromXbeibeixURL}/video`);
}
updateArrayDataInBackup(backup, 'cover', response.responseXML.querySelector('div.col-4 > img').getAttribute('src'), undefined, `${settings.getFromXbeibeixURL}/video`);
updateArrayDataInBackup(backup, 'upperName', response.responseXML.querySelector('div.input-group.mb-2 > input').value, undefined, `${settings.getFromXbeibeixURL}/video`);
backup.xbeibeix = { value: true, ts: getCurrentTs() };
spanX.style.color = '#00ff00';
} else {
if (enableDebug) console.log('从贝贝工具站获取无效数据');
if (enableDebug) consoleAVBVTitle('debug', AVBVTitle);
if (enableDebug) console.debug(response);
backup.xbeibeix = { value: false, ts: getCurrentTs() };
spanX.style.color = '#ff0000';
}
}
function addMessage(msg, smallFontSize, border) {
let px;
if (smallFontSize) {
px = newFreshSpace ? 11 : 10;
} else {
px = newFreshSpace ? 13 : 12;
}
const p = document.createElement('p');
p.innerHTML = msg;
p.style.fontSize = `${px}px`;
if (border) {
p.style.borderTop = '1px solid #ff0000';
}
divMessage.appendChild(p);
if (divMessageHeightFixed) {
divMessage.scrollTop = divMessage.scrollHeight;
} else {
if (newFreshSpace) {
if (divMessage.scrollHeight > 320) {
divMessage.classList.add('backup-divMessage-heightFixed-newFreshSpace');
divMessageHeightFixed = true;
divMessage.scrollTop = divMessage.scrollHeight;
}
} else {
if (divMessage.scrollHeight > 280) {
divMessage.classList.add('backup-divMessage-heightFixed');
divMessageHeightFixed = true;
divMessage.scrollTop = divMessage.scrollHeight;
}
}
}
divMessage.scrollIntoView({ behavior: 'instant', block: 'nearest' });
}
function clearMessage() {
while (divMessage.firstChild) {
divMessage.removeChild(divMessage.firstChild);
}
divMessage.classList.remove('backup-divMessage-heightFixed' + classAppendNewFreshSpace);
divMessageHeightFixed = false;
}
function addMessageAVBVTitle(AVBVTitle) {
addMessage(`AV号: ${AVBVTitle.AV}`, true);
addMessage(`BV号: ${AVBVTitle.BV}`, true);
if (AVBVTitle.title) {
addMessage(`标题: ${AVBVTitle.title.slice(0, 13)}`, true);
}
}
function consoleAVBVTitle(type, AVBVTitle) {
switch (type) {
case 'debug':
console.debug(`AV号: ${AVBVTitle.AV}`);
console.debug(`BV号: ${AVBVTitle.BV}`);
console.debug(`标题: ${AVBVTitle.title.slice(0, 13)}`);
break;
case 'log':
console.log(`AV号: ${AVBVTitle.AV}`);
console.log(`BV号: ${AVBVTitle.BV}`);
console.log(`标题: ${AVBVTitle.title.slice(0, 13)}`);
break;
case 'warn':
console.warn(`AV号: ${AVBVTitle.AV}`);
console.warn(`BV号: ${AVBVTitle.BV}`);
console.warn(`标题: ${AVBVTitle.title.slice(0, 13)}`);
break;
case 'error':
console.error(`AV号: ${AVBVTitle.AV}`);
console.error(`BV号: ${AVBVTitle.BV}`);
if (AVBVTitle.title) {
console.error(`标题: ${AVBVTitle.title.slice(0, 13)}`);
}
break;
default:
throw Error('invalid type');
}
}
function catchUnknownError(error) {
addMessage('发生未知错误, 请反馈该问题', false, true);
addMessage(error.stack, true);
console.error(error);
}
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function getCurrentTs() {
return Math.floor(Date.now() / 1000);
}
function abortActiveControllers() {
for (const controller of activeControllers) {
controller.abort();
}
}
function formatTsTimeFavorite(t) {
const e = new Date();
const n = e.getTime();
const r = t.getTime();
const o = n - r;
return o < 6e4
? '刚刚'
: o < 36e5
? Math.floor(o / 6e4) + '分钟前'
: o < 864e5
? Math.floor(o / 36e5) + '小时前'
: r >= new Date(e.getFullYear(), e.getMonth(), e.getDate() - 1).getTime()
? '昨天'
: r >= new Date(e.getFullYear(), 0, 1).getTime()
? (t.getMonth() + 1) + '-' + t.getDate()
// : o < 63072e6
// ? t.getFullYear() + '-' + (t.getMonth() + 1) + '-' + t.getDate()
// : '2年前';
: t.getFullYear() + '-' + (t.getMonth() + 1) + '-' + t.getDate();
}
function formatTsYYMMDD_HHMMSS(ts) {
const date = new Date(ts * 1000);
const year = String(date.getFullYear()).slice(2);
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}${month}${day}_${hours}${minutes}${seconds}`;
}
function formatTsTimePublish(e) {
let n = new Date(e);
let u = Date.now();
if (u - e <= 6e4) {
return '刚刚';
}
if (u - e < 36e5) {
return Math.floor((u - e) / 6e4) + '分钟前';
}
if (u - e < 864e5) {
return Math.floor((u - e) / 36e5) + '小时前';
}
if (new Date().setHours(0, 0, 0, 0) - e < 864e5) {
return '昨天';
}
let l = n.getFullYear();
let c = '0'.concat(n.getMonth() + 1).slice(-2);
let f = '0'.concat(n.getDate()).slice(-2);
return l === new Date().getFullYear() ? ''.concat(c, '-').concat(f) : ''.concat(l, '-').concat(c, '-').concat(f);
}
function decodeHTMLEntities(str) {
return new DOMParser().parseFromString(`<!doctype html><body>${str}`, 'text/html').body.textContent;
}
function updateArrayDataInBackup(backup, key, value, ts, from) {
if (!value) {
return;
}
if (!ts) {
ts = 0;
}
if (key === 'cover' || key === 'upperAvatar') {
value = value.replace(getHttpsFromURLRegex, '').replace(getAvifFromURLRegex, '');
}
if (!backup[key]) {
backup[key] = [];
const data = { value, ts, from };
backup[key].push(data);
return;
}
let target;
target = backup[key].find(el => el.value === value);
if (target) {
if (target.ts <= ts) {
target.ts = ts;
target.from = from;
backup[key].sort((a, b) => a.ts - b.ts);
}
return;
}
if (key === 'cover' || key === 'upperAvatar') {
target = backup[key].find(el => el.value.match(getFilenameFromURLRegex)[0] === value.match(getFilenameFromURLRegex)[0]);
if (target) {
if (target.ts <= ts) {
target.value = value;
target.ts = ts;
target.from = from;
backup[key].sort((a, b) => a.ts - b.ts);
}
return;
}
} else if (key === 'intro') {
target = backup.intro.find(el => el.value.replaceAll('\r', '') === value);
if (target) {
return;
}
target = backup.intro.find(el => el.value === value.replaceAll('\r', ''));
if (target) {
target.value = value;
target.ts = ts;
target.from = from;
backup.intro.sort((a, b) => a.ts - b.ts);
return;
}
if (value.length >= 255 || ((from.includes('xbeibeix') || from.includes('bbdownloader')) && value.length >= 200)) {
target = backup.intro.find(el => el.value.replaceAll('\r', '').startsWith(value.replaceAll('\r', '')));
if (target) {
return;
}
target = backup.intro.find(el => value.replaceAll('\r', '').startsWith(el.value.replaceAll('\r', '')));
if (target) {
target.value = value;
target.ts = ts;
target.from = from;
backup.intro.sort((a, b) => a.ts - b.ts);
return;
}
}
}
const data = { value, ts, from };
backup[key].push(data);
backup[key].sort((a, b) => a.ts - b.ts);
}
function updateTimeFavoriteInBackup(backup, value, fid) {
if (!value) {
value = 0;
}
if (!backup.timeFavorite) {
backup.timeFavorite = [];
const data = { value, fid };
backup.timeFavorite.push(data);
return true;
} else {
const target = backup.timeFavorite.find(el => el.fid === fid);
if (target) {
if (target.value < value) {
target.value = value;
backup.timeFavorite.sort((a, b) => a.value - b.value);
return true;
}
} else {
const data = { value, fid };
backup.timeFavorite.push(data);
backup.timeFavorite.sort((a, b) => a.value - b.value);
return true;
}
}
}
function updatePagesInBackup(backup, index, title, firstFrame, cid, ts, from) {
if (!index && index !== 0) {
index = null;
}
if (title) {
if (typeof title !== 'object') {
title = [title];
}
} else {
title = null;
}
if (firstFrame) {
firstFrame = firstFrame.replace(getHttpsFromURLRegex, '').replace(getAvifFromURLRegex, '');
} else {
firstFrame = null;
}
if (!cid && cid !== 0) {
cid = null;
}
if (!ts) {
ts = 0;
}
if (!backup.pages) {
backup.pages = [];
const data = { index, title, firstFrame, cid, ts, from };
backup.pages.push(data);
} else {
const target = backup.pages.find(el => el.cid === cid);
if (target) {
let modified = false;
if (index) {
if (!target.index) {
target.index = index;
modified = true;
} else if (target.index !== index) {
if (enableDebug) console.warn('updatePagesInBackup index不一致');
if (enableDebug) console.warn(`旧: ${target.index}`);
if (enableDebug) console.warn(`新: ${index}`);
target.index = index;
modified = true;
}
}
if (title) {
if (!target.title) {
target.title = title;
modified = true;
} else {
title.forEach(el => {
if (!target.title.find(ele => ele === el)) {
if (enableDebug) console.warn('updatePagesInBackup title不一致');
target.title.push(el);
modified = true;
}
});
}
}
if (firstFrame) {
if (!target.firstFrame) {
target.firstFrame = firstFrame;
modified = true;
} else if (target.firstFrame !== firstFrame) {
if (enableDebug) console.warn('updatePagesInBackup firstFrame不一致');
if (enableDebug) console.warn(`旧: ${target.firstFrame}`);
if (enableDebug) console.warn(`新: ${firstFrame}`);
// target.firstFrame = firstFrame;
// modified = true;
}
}
if (target.ts <= ts) {
target.ts = ts;
modified = true;
}
if (modified) {
target.from = from;
backup.pages.sort((a, b) => {
if (a.index !== b.index) {
return a.index - b.index;
} else if (a.ts !== b.ts) {
return a.ts - b.ts;
} else {
return a.cid - b.cid;
}
});
}
} else {
if (backup.pages.find(el => el.index === index)) {
if (enableDebug) console.warn(`updatePagesInBackup 分集${index}更改`);
}
const data = { index, title, firstFrame, cid, ts, from };
backup.pages.push(data);
backup.pages.sort((a, b) => {
if (a.index !== b.index) {
return a.index - b.index;
} else if (a.ts !== b.ts) {
return a.ts - b.ts;
} else {
return a.cid - b.cid;
}
});
}
}
}
async function appendParamsForGetFromApi(fid, pageNumber, pageSize) {
const inputKeyword = document.querySelector(newFreshSpace ? 'input.fav-list-header-filter__search' : 'input.search-fav-input');
let keyword = '';
if (inputKeyword) {
keyword = encodeURIComponent(inputKeyword.value);
}
if (enableDebug) console.log(`keyword: ${decodeURIComponent(keyword)}`);
if (enableDebug) console.log(keyword);
if (!newFreshSpace) {
const divFilterOrder = document.querySelector('div.fav-filters > div:nth-child(3) > span');
let orderText = '收藏';
if (divFilterOrder) {
orderText = divFilterOrder.innerText;
}
if (orderText.includes('收藏')) {
order = 'mtime';
} else if (orderText.includes('播放')) {
order = 'view';
} else if (orderText.includes('投稿')) {
order = 'pubtime';
} else {
throw ['无法确定各个视频的排序方式, 请反馈该问题'];
}
}
if (enableDebug) console.log(`order: ${order}`);
const divType = document.querySelector(newFreshSpace ? 'div.vui_input__prepend' : 'div.search-types');
let typeText = '当前';
if (divType) {
typeText = divType.innerText;
}
if (newFreshSpace && keyword === '') {
typeText = '当前';
}
if (enableDebug) console.log(`typeText: ${typeText}`);
let type;
if (typeText.includes('当前')) {
type = 0;
} else if (typeText.includes('全部')) {
type = 1;
} else {
throw ['无法确定搜索的范围为当前收藏夹还是全部收藏夹, 请反馈该问题'];
}
if (enableDebug) console.log(`type: ${type}`);
const divTid = document.querySelector(newFreshSpace ? 'div.fav-list-header-collapse div.radio-filter__item--active' : 'div.fav-filters > div:nth-child(2) > span');
let tidText = '全部分区';
if (divTid) {
tidText = divTid.innerText;
}
if (enableDebug) console.log(`tidText: ${tidText}`);
let tid;
if (tidText.includes('全部')) {
tid = 0;
} else {
const UID = parseInt(location.href.match(getUIDFromURLRegex)[1], 10);
const response = await new Promise((resolve, reject) => {
GM.xmlHttpRequest({
method: 'GET',
url: `https://api.bilibili.com/x/v3/fav/resource/partition?up_mid=${UID}&media_id=${fid}` + (newFreshSpace ? '&web_location=333.1387' : ''),
timeout: 5000,
responseType: 'json',
onload: (res) => resolve(res),
onerror: (res) => reject(['请求失败', 'api.bilibili.com/x/v3/fav/resource/partition', res.error]),
ontimeout: () => reject(['请求超时', 'api.bilibili.com/x/v3/fav/resource/partition'])
});
});
const partitions = response.response.data;
const target = partitions.find(el => tidText.includes(el.name));
if (target) {
tid = target.tid;
} else {
throw ['无法确定选择的分区, 请反馈该问题'];
}
}
if (enableDebug) console.log(`tid: ${tid}`);
if (enableDebug) console.log(`https://api.bilibili.com/x/v3/fav/resource/list?media_id=${fid}&pn=${pageNumber}&ps=${pageSize}&keyword=${keyword}&order=${order}&type=${type}&tid=${tid}&platform=web` + (newFreshSpace ? '&web_location=333.1387' : ''));
return (`https://api.bilibili.com/x/v3/fav/resource/list?media_id=${fid}&pn=${pageNumber}&ps=${pageSize}&keyword=${keyword}&order=${order}&type=${type}&tid=${tid}&platform=web` + (newFreshSpace ? '&web_location=333.1387' : ''));
}
function validateInputText(event) {
const inputText = event.target;
let value = inputText.value.trim();
const def = parseInt(inputText.getAttribute('backup-def'), 10);
if (!value || isNaN(value)) {
value = def;
} else {
value = parseInt(value, 10);
const min = parseInt(inputText.getAttribute('backup-min'), 10);
const max = parseInt(inputText.getAttribute('backup-max'), 10);
if (value < min) {
value = min;
} else if (value > max) {
value = max;
}
}
inputText.value = value;
const key = inputText.getAttribute('backup-setting');
settings[key] = value;
GM_setValue('settings', settings);
}
// async function mainNewFreshSpace(mutations) {
// async function mainNewFreshSpace() {
// mutations_count++;
// console.debug('mutations_count' + mutations_count);
// for (const mutation of mutations) {
// mutation_count++;
// console.debug('mutation_count' + mutation_count);
// console.debug(mutation);
// }
// if (firstTime) {
// firstTime = false;
// } else {
// mutations = mutations.reverse();
// }
// for (const mutation of mutations) {
// if (mutation.addedNodes.length) {
// const items = document.querySelectorAll('div.items__item');
// for (const item of items) {
// console.debug(mutation.addedNodes[0].querySelectorAll('a'));
// console.debug(mutation.addedNodes[0].querySelectorAll('a')[1].innerText);
// mutation.addedNodes[0].querySelectorAll('a')[1].style.color = 'red';
// }
// }
})();