🏠 Home 

Greasy Fork is available in English.

bilibili favlist backup

automatically backup info of videos in favlist

// ==UserScript==
// @name              bilibili favlist backup
// @name:zh-CN        哔哩哔哩(B站|Bilibili)收藏夹Fix (备份视频信息)
// @name:zh-TW        哔哩哔哩(B站|Bilibili)收藏夹Fix (备份视频信息)
// @namespace         http://tampermonkey.net/
// @version           25
// @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>' +
'修复: 旧版个人空间中指定关键词后无法从B站接口获取数据的问题';
const version = 25;
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 getUIDFromURLRegex = /https:\/\/space\.bilibili\.com\/(\d+)/;
const getBVFromURLRegex = /video\/(BV\w{10})/;
const getHttpsFromURLRegex = /^(https?:\/\/|\/\/)/;
const getJsonFromBiliplusRegex = /window\.addEventListener\('DOMContentLoaded',function\(\){view\((.+)\);}\);/;
const getParamsWithSignFromBiliplusRegex = /api\/view_all(.+)'/;
const getFilenameFromURLRegex = /[^/]+(?:\.[a-zA-Z0-9]+)$/;
const getAvifFromURLRegex = /@.*/;
let onFavlistPage = false;
let enableAutoNextPage = false;
let enableAutoNextFavlist = false;
let enableDebug = false;
let newFreshSpace;
let classAppendNewFreshSpace;
let pageSize;
let firstTimeMain = true;
let di#####age;
let di#####ageHeightFixed = 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',
'biliplusExtra',
'jijidown',
'jijidownExtra',
'xbeibeix',
];
const settings = GM_getValue('settings', {
processNormal: true,
processDisabled: true,
enableGetFromApi: true,
enableUpdateGetFromApi: true,
intervalGetFromApi: 5,
enableGetFromApiExtra: false,
enableGetThumbnails: false,
enableUpdateGetFromApiExtra: true,
intervalGetFromApiExtra: 5,
enableGetFromBiliplus: true,
enableUpdateGetFromBiliplus: false,
intervalGetFromBiliplus: 10,
enableGetFromBiliplusExtra: false,
enableUpdateGetFromBiliplusExtra: false,
intervalGetFromBiliplusExtra: 10,
enableGetFromJijidown: false,
enableUpdateGetFromJijidown: false,
intervalGetFromJijidown: 10,
enableGetFromJijidownExtra: false,
enableUpdateGetFromJijidownExtra: false,
intervalGetFromJijidownExtra: 10,
getFromJijidownURL: 'www.jijidown.com',
enableGetFromXbeibeix: false,
enableUpdateGetFromXbeibeix: false,
intervalGetFromXbeibeix: 10,
getFromXbeibeixURL: 'xbeibeix.com',
intervalAutoNextPage: 5,
requestTimeout: 10,
delayBeforeMain: 300,
appendDropdownCover: true,
appendDropdownLocal: true,
appendDropdownJump: true,
appendDropdownReset: true,
displayAdvancedControls: false,
exportBackupWithoutTsFrom: false,
version: 0,
defaultUID: null,
defaultFavlistFid: null,
});
///////////////////////////////////////////////////////////////////////////////////
// enableDebug = true;
// settings.delayBeforeMain = 500;
// 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);
}
// v19
if (!settings.hasOwnProperty('displayAdvancedControls')) {
settings.displayAdvancedControls = false;
settings.advancedEnableUpdateGetFromApi = true;
settings.advancedEnableUpdateGetFromApiExtra = true;
settings.advancedEnableUpdateGetFromBiliplus = false;
settings.advancedEnableUpdateGetFromJijidown = false;
settings.advancedEnableUpdateGetFromJijidownExtra = false;
settings.advancedEnableUpdateGetFromXbeibeix = false;
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);
}
// v19
if (settings.hasOwnProperty('advancedDisableUpdateGetFromApi')) {
settings.advancedEnableUpdateGetFromApi = !settings.advancedDisableUpdateGetFromApi;
settings.advancedEnableUpdateGetFromApiExtra = !settings.advancedDisableUpdateGetFromApiExtra;
settings.advancedEnableUpdateGetFromBiliplus = !settings.advancedDisableUpdateGetFromBiliplus;
settings.advancedEnableUpdateGetFromJijidown = !settings.advancedDisableUpdateGetFromJijidown;
settings.advancedEnableUpdateGetFromJijidownExtra = !settings.advancedDisableUpdateGetFromJijidownExtra;
settings.advancedEnableUpdateGetFromXbeibeix = !settings.advancedDisableUpdateGetFromXbeibeix;
delete settings.advancedDisableUpdateGetFromApi;
delete settings.advancedDisableUpdateGetFromApiExtra;
delete settings.advancedDisableUpdateGetFromBiliplus;
delete settings.advancedDisableUpdateGetFromJijidown;
delete settings.advancedDisableUpdateGetFromJijidownExtra;
delete settings.advancedDisableUpdateGetFromXbeibeix;
GM_setValue('settings', settings);
}
// v20
if (settings.hasOwnProperty('advancedIntervalAutoNextPage')) {
settings.enableUpdateGetFromApi = settings.advancedEnableUpdateGetFromApi;
settings.enableUpdateGetFromApiExtra = settings.advancedEnableUpdateGetFromApiExtra;
settings.enableUpdateGetFromBiliplus = settings.advancedEnableUpdateGetFromBiliplus;
settings.enableUpdateGetFromJijidown = settings.advancedEnableUpdateGetFromJijidown;
settings.enableUpdateGetFromJijidownExtra = settings.advancedEnableUpdateGetFromJijidownExtra;
settings.enableUpdateGetFromXbeibeix = settings.advancedEnableUpdateGetFromXbeibeix;
settings.intervalGetFromApi = settings.advancedIntervalGetFromApi;
settings.intervalGetFromApiExtra = settings.advancedIntervalGetFromApiExtra;
settings.intervalGetFromBiliplus = settings.advancedIntervalGetFromBiliplus;
settings.intervalGetFromJijidown = settings.advancedIntervalGetFromJijidown;
settings.intervalGetFromJijidownExtra = settings.advancedIntervalGetFromJijidownExtra;
settings.intervalGetFromXbeibeix = settings.advancedIntervalGetFromXbeibeix;
settings.intervalAutoNextPage = settings.advancedIntervalAutoNextPage;
delete settings.advancedEnableUpdateGetFromApi;
delete settings.advancedEnableUpdateGetFromApiExtra;
delete settings.advancedEnableUpdateGetFromBiliplus;
delete settings.advancedEnableUpdateGetFromJijidown;
delete settings.advancedEnableUpdateGetFromJijidownExtra;
delete settings.advancedEnableUpdateGetFromXbeibeix;
delete settings.advancedIntervalGetFromApi;
delete settings.advancedIntervalGetFromApiExtra;
delete settings.advancedIntervalGetFromBiliplus;
delete settings.advancedIntervalGetFromJijidown;
delete settings.advancedIntervalGetFromJijidownExtra;
delete settings.advancedIntervalGetFromXbeibeix;
delete settings.advancedIntervalAutoNextPage;
GM_setValue('settings', settings);
}
// v20
if (settings.hasOwnProperty('advancedRequestTimeout')) {
settings.requestTimeout = settings.advancedRequestTimeout;
delete settings.advancedRequestTimeout;
GM_setValue('settings', settings);
}
// v20
if (!settings.hasOwnProperty('requestTimeout')) {
settings.requestTimeout = 10;
GM_setValue('settings', settings);
}
// v20
if (settings.hasOwnProperty('advancedExportBackupWithoutTsFrom')) {
settings.exportBackupWithoutTsFrom = settings.advancedExportBackupWithoutTsFrom;
delete settings.advancedExportBackupWithoutTsFrom;
GM_setValue('settings', settings);
}
// v20
if (!settings.hasOwnProperty('exportBackupWithoutTsFrom')) {
settings.exportBackupWithoutTsFrom = false;
GM_setValue('settings', settings);
}
// v20
if (!settings.hasOwnProperty('enableGetThumbnails')) {
settings.enableGetThumbnails = false;
GM_setValue('settings', settings);
}
// v21
if (!settings.hasOwnProperty('delayBeforeMain')) {
settings.delayBeforeMain = 300;
settings.appendDropdownCover = true;
settings.appendDropdownLocal = true;
settings.appendDropdownJump = true;
settings.appendDropdownReset = true;
GM_setValue('settings', settings);
}
// v22
if (!settings.hasOwnProperty('enableGetFromBiliplusExtra')) {
settings.enableGetFromBiliplusExtra = false;
settings.enableUpdateGetFromBiliplusExtra = false;
settings.intervalGetFromBiliplusExtra = 10;
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(settings.delayBeforeMain);
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 () => {
abortActiveControllers();
if (enableDebug) console.debug('callback itemsObserver');
await delay(settings.delayBeforeMain);
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;
enableAutoNextPage = false;
enableAutoNextFavlist = false;
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 currentFavlist;
if (newFreshSpace) {
currentFavlist = document.querySelector('div.vui_sidebar-item--active');
if (!document.querySelector('div.fav-collapse').contains(currentFavlist)) {
if (enableDebug) console.log('不处理特殊收藏夹');
return;
}
} else {
currentFavlist = document.querySelector('.fav-item.cur');
if (!document.querySelector('div.nav-container').contains(currentFavlist)) {
if (enableDebug) console.log('不处理特殊收藏夹');
return;
}
}
let fid;
if (newFreshSpace) {
const getFidFromURLMatch = location.href.match(getFidFromURLRegex);
if (getFidFromURLMatch) {
fid = parseInt(getFidFromURLMatch[1], 10);
if (!settings.defaultFavlistFid && !currentFavlist.parentNode.getAttribute('id')) {
settings.defaultFavlistFid = fid;
GM_setValue('settings', settings);
}
} else if (settings.defaultFavlistFid) {
fid = settings.defaultFavlistFid;
} else {
throw ['无法获取当前收藏夹的fid, 刷新页面可能有帮助'];
}
} else {
fid = parseInt(currentFavlist.getAttribute('fid'), 10);
}
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');
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');
}
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 = 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,
biliplusExtra: null,
jijidown: null,
jijidownExtra: null,
xbeibeix: null,
});
if (!backup.BV) {
backup.BV = AVBVTitle.BV;
GM_setValue(AVBVTitle.BV, backup);
}
AVBVTitle.AV = backup.AV;
formatBackup(backup, true, AVBVTitle.BV);
if (updateTimeFavoriteNeeded() && updateTimeFavoriteInBackup(backup, undefined, fid)) {
GM_setValue(AVBVTitle.BV, backup);
}
const functions = [];
try {
if (newFreshSpace) {
if (backup.timePublish) {
spanFavTime.textContent = `投稿于:${formatTsTimePublish(1000 * backup.timePublish)}`;
spanFavTime.setAttribute('title', new Date(1000 * backup.timePublish).toLocaleString());
}
} else {
if (backup.timeFavorite) {
const target = backup.timeFavorite.find(el => el.fid === fid);
if (target && target.value) {
spanFavTime.textContent = `收藏于:${formatTsTimeFavorite(new Date(1000 * target.value))}`;
spanFavTime.setAttribute('title', new Date(1000 * target.value).toLocaleString());
}
}
}
if (controller.signal.aborted) {
throw new DOMException('', 'AbortError');
}
if (settings.enableGetFromApi) {
if (!backup.api || (settings.enableUpdateGetFromApi && getCurrentTs() - backup.api.ts > 3600 * settings.intervalGetFromApi)) {
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 (updateTimeFavoriteNeeded() && 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 (controller.signal.aborted) {
throw new DOMException('', 'AbortError');
}
if (settings.enableGetFromApiExtra) {
if (!backup.apiExtra || (settings.enableUpdateGetFromApiExtra && getCurrentTs() - backup.apiExtra.ts > 3600 * 24 * settings.intervalGetFromApiExtra)) {
await getFromApiExtra(AVBVTitle, backup, spanA, disabled, controller);
} else {
spanA.style.color = backup.apiExtra.value ? '#008000' : '#800000';
}
}
if (controller.signal.aborted) {
throw new DOMException('', 'AbortError');
}
if (settings.enableGetFromJijidown) {
if (!backup.jijidown || (settings.enableUpdateGetFromJijidown && getCurrentTs() - backup.jijidown.ts > 3600 * 24 * 7 * settings.intervalGetFromJijidown)) {
functions.push(getFromJijidown(AVBVTitle, backup, spanJ));
} else {
if (settings.enableGetFromJijidownExtra) {
if (!backup.jijidownExtra || (settings.enableUpdateGetFromJijidownExtra && getCurrentTs() - backup.jijidownExtra.ts > 3600 * 24 * 7 * settings.intervalGetFromJijidownExtra)) {
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.enableUpdateGetFromXbeibeix && getCurrentTs() - backup.xbeibeix.ts > 3600 * 24 * 7 * settings.intervalGetFromXbeibeix)) {
functions.push(getFromXbeibeix(AVBVTitle, backup, spanX));
} else {
spanX.style.color = backup.xbeibeix.value ? '#00ff00' : '#ff0000';
}
}
if (settings.enableGetFromBiliplus) {
if (!backup.biliplus || (settings.enableUpdateGetFromBiliplus && getCurrentTs() - backup.biliplus.ts > 3600 * 24 * 7 * settings.intervalGetFromBiliplus)) {
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);
}
if (controller.signal.aborted) {
throw new DOMException('', 'AbortError');
}
if (settings.enableGetFromBiliplusExtra) {
if (!backup.biliplusExtra || (settings.enableUpdateGetFromBiliplusExtra && getCurrentTs() - backup.biliplusExtra.ts > 3600 * 24 * 7 * settings.intervalGetFromBiliplusExtra)) {
await getFromBiliplusExtra(AVBVTitle, backup, spanB);
} else {
spanB.style.color = backup.biliplusExtra.value ? '#008000' : '#800000';
}
}
} 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');
if (enableDebug) {
if (!img.getAttribute('src').endsWith('@672w_378h_1c.avif')) {
addMessage('封面avif已更改');
console.warn('封面avif已更改');
}
}
} 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.slice(8)}@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.slice(8)}@320w_200h_1c_!web-space-favlist-video.avif`);
sourceWebp.setAttribute('srcset', `//${backup.cover[backup.cover.length - 1].value.slice(8)}@320w_200h_1c_!web-space-favlist-video.webp`);
img.setAttribute('src', `//${backup.cover[backup.cover.length - 1].value.slice(8)}@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.slice(8)}@672w_378h_1c.avif`);
} else {
sourceAvif.setAttribute('srcset', `//${backup.cover[i].value.slice(8)}@320w_200h_1c_!web-space-favlist-video.avif`);
sourceWebp.setAttribute('srcset', `//${backup.cover[i].value.slice(8)}@320w_200h_1c_!web-space-favlist-video.webp`);
img.setAttribute('src', `//${backup.cover[i].value.slice(8)}@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);
}
}
} 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.intervalAutoNextPage);
if (controller.signal.aborted) {
throw new DOMException('', 'AbortError');
}
if (enableAutoNextPage) {
pager.click();
}
} else if (enableAutoNextFavlist) {
if (!currentFavlist.parentNode.getAttribute('id')) {
if (document.querySelector('div.fav-sortable-list').childElementCount) {
await delay(1000 * settings.intervalAutoNextPage);
if (controller.signal.aborted) {
throw new DOMException('', 'AbortError');
}
if (enableAutoNextFavlist) {
document.querySelector('div.fav-sortable-list').firstElementChild.querySelector('div').click();
}
}
} else {
const nextFavlist = currentFavlist.parentNode.nextElementSibling;
if (nextFavlist) {
await delay(1000 * settings.intervalAutoNextPage);
if (controller.signal.aborted) {
throw new DOMException('', 'AbortError');
}
if (enableAutoNextFavlist) {
nextFavlist.querySelector('div').click();
}
}
}
}
} else {
const pager = document.querySelector('li.be-pager-next');
if (pager && !pager.classList.contains('be-pager-disabled')) {
await delay(1000 * settings.intervalAutoNextPage);
if (controller.signal.aborted) {
throw new DOMException('', 'AbortError');
}
if (enableAutoNextPage) {
pager.click();
}
} else if (enableAutoNextFavlist) {
if (currentFavlist.nodeName === 'DIV') {
if (document.querySelector('ul.fav-list').childElementCount) {
await delay(1000 * settings.intervalAutoNextPage);
if (controller.signal.aborted) {
throw new DOMException('', 'AbortError');
}
if (enableAutoNextFavlist) {
document.querySelector('ul.fav-list').firstElementChild.querySelector('a').click();
}
}
} else {
const nextFavlist = currentFavlist.nextElementSibling;
if (nextFavlist) {
await delay(1000 * settings.intervalAutoNextPage);
if (controller.signal.aborted) {
throw new DOMException('', 'AbortError');
}
if (enableAutoNextFavlist) {
nextFavlist.querySelector('a').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 16px;
}
.backup-div-second-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: 28px;
height: 14px;
border-radius: 2px;
font-size: 14px;
}
.backup-inputText-newFreshSpace {
width: 32px;
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-di#####age, .backup-di#####age-newFreshSpace {
overflow-y: auto;
background-color: #eeeeee;
line-height: 1.5;
scrollbar-width: none;
}
.backup-di#####age {
margin: 2px;
}
.backup-di#####age-heightFixed {
height: 280px;
}
.backup-di#####age::-webkit-scrollbar {
display: none;
}
.backup-di#####age-newFreshSpace {
margin: 2px 0;
}
.backup-di#####age-heightFixed-newFreshSpace {
height: 320px;
}
.backup-di#####age-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;
if (!settings.processNormal && !settings.processDisabled) {
divLabelEnableGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetThumbnails.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL1.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL2.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromXbeibeix.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) {
divLabelEnableUpdateGetFromApi.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromApi) {
divLabelIntervalGetFromApi.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divLabelEnableGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromApiExtra) {
divLabelEnableGetThumbnails.classList.remove('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromApiExtra) {
divLabelIntervalGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
}
divLabelEnableGetFromBiliplus.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromBiliplus) {
divLabelEnableUpdateGetFromBiliplus.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromBiliplus) {
divLabelIntervalGetFromBiliplus.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
if (settings.enableGetFromApi && settings.enableGetFromBiliplus) {
divLabelEnableGetFromBiliplusExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromBiliplusExtra) {
divLabelEnableUpdateGetFromBiliplusExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromBiliplusExtra) {
divLabelIntervalGetFromBiliplusExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
}
divLabelEnableGetFromJijidown.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromJijidown) {
divLabelEnableUpdateGetFromJijidown.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromJijidown) {
divLabelIntervalGetFromJijidown.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divLabelEnableGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromJijidownExtra) {
divLabelEnableUpdateGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromJijidownExtra) {
divLabelIntervalGetFromJijidownExtra.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) {
divLabelEnableUpdateGetFromXbeibeix.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromXbeibeix) {
divLabelIntervalGetFromXbeibeix.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divSwitchGetFromXbeibeixURL1.classList.remove('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL2.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
GM_setValue('settings', settings);
} 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;
if (!settings.processNormal && !settings.processDisabled) {
divLabelEnableGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetThumbnails.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL1.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL2.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromXbeibeix.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) {
divLabelEnableUpdateGetFromApi.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromApi) {
divLabelIntervalGetFromApi.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divLabelEnableGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromApiExtra) {
divLabelEnableGetThumbnails.classList.remove('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromApiExtra) {
divLabelIntervalGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
}
divLabelEnableGetFromBiliplus.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromBiliplus) {
divLabelEnableUpdateGetFromBiliplus.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromBiliplus) {
divLabelIntervalGetFromBiliplus.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
if (settings.enableGetFromApi) {
divLabelEnableGetFromBiliplusExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromBiliplusExtra) {
divLabelEnableUpdateGetFromBiliplusExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromBiliplusExtra) {
divLabelIntervalGetFromBiliplusExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
}
}
divLabelEnableGetFromJijidown.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromJijidown) {
divLabelEnableUpdateGetFromJijidown.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromJijidown) {
divLabelIntervalGetFromJijidown.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divLabelEnableGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromJijidownExtra) {
divLabelEnableUpdateGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromJijidownExtra) {
divLabelIntervalGetFromJijidownExtra.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) {
divLabelEnableUpdateGetFromXbeibeix.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromXbeibeix) {
divLabelIntervalGetFromXbeibeix.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divSwitchGetFromXbeibeixURL1.classList.remove('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL2.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelProcessDisabled.insertAdjacentElement('afterbegin', checkboxProcessDisabled);
const divLabelEnableGetFromApi = document.createElement('div');
divLabelEnableGetFromApi.classList.add('backup-div-first' + 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主头像地址, 上传时间, 发布时间, 添加到当前收藏夹的时间, 第1个分集的cid (均为最新版本)\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;
settings.enableGetThumbnails = false;
checkboxEnableGetThumbnails.checked = false;
settings.enableGetFromBiliplusExtra = false;
checkboxEnableGetFromBiliplusExtra.checked = false;
divLabelEnableUpdateGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetThumbnails.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelEnableUpdateGetFromApi.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromApi) {
divLabelIntervalGetFromApi.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divLabelEnableGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromApiExtra) {
divLabelEnableGetThumbnails.classList.remove('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromApiExtra) {
divLabelIntervalGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
if (settings.enableGetFromBiliplus) {
divLabelEnableGetFromBiliplusExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromBiliplusExtra) {
divLabelEnableUpdateGetFromBiliplusExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromBiliplusExtra) {
divLabelIntervalGetFromBiliplusExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
}
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableGetFromApi.insertAdjacentElement('afterbegin', checkboxEnableGetFromApi);
const divLabelEnableUpdateGetFromApi = document.createElement('div');
divLabelEnableUpdateGetFromApi.classList.add('backup-div-second' + classAppendNewFreshSpace, 'backup-advanced');
divLabelEnableUpdateGetFromApi.setAttribute('title',
'默认: 开启\n' +
'关闭后每个视频从B站接口只会获取一次数据。\n' +
'不建议关闭, 因为某些视频的信息可能会经常更新。');
divControls.appendChild(divLabelEnableUpdateGetFromApi);
const labelEnableUpdateGetFromApi = document.createElement('label');
labelEnableUpdateGetFromApi.classList.add('backup-label' + classAppendNewFreshSpace);
labelEnableUpdateGetFromApi.textContent = '启用更新';
divLabelEnableUpdateGetFromApi.appendChild(labelEnableUpdateGetFromApi);
const checkboxEnableUpdateGetFromApi = document.createElement('input');
checkboxEnableUpdateGetFromApi.type = 'checkbox';
checkboxEnableUpdateGetFromApi.checked = settings.enableUpdateGetFromApi;
checkboxEnableUpdateGetFromApi.addEventListener('change', () => {
try {
settings.enableUpdateGetFromApi = checkboxEnableUpdateGetFromApi.checked;
if (!settings.enableUpdateGetFromApi) {
divLabelIntervalGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelIntervalGetFromApi.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableUpdateGetFromApi.insertAdjacentElement('afterbegin', checkboxEnableUpdateGetFromApi);
const divLabelIntervalGetFromApi = document.createElement('div');
divLabelIntervalGetFromApi.classList.add('backup-div-second' + classAppendNewFreshSpace, 'backup-advanced');
divLabelIntervalGetFromApi.setAttribute('title',
'默认: 5小时\n' +
'脚本处理某个视频时, 如果发现距离上次从B站接口获取到该视频的数据已经超过了设定的时间间隔, 则会再次从B站接口获取该视频的数据。');
divControls.appendChild(divLabelIntervalGetFromApi);
const labelIntervalGetFromApi = document.createElement('label');
labelIntervalGetFromApi.classList.add('backup-label' + classAppendNewFreshSpace);
divLabelIntervalGetFromApi.appendChild(labelIntervalGetFromApi);
const inputTextIntervalGetFromApi = document.createElement('input');
inputTextIntervalGetFromApi.type = 'text';
inputTextIntervalGetFromApi.classList.add('backup-inputText' + classAppendNewFreshSpace);
inputTextIntervalGetFromApi.value = settings.intervalGetFromApi;
inputTextIntervalGetFromApi.setAttribute('backup-def', 5);
inputTextIntervalGetFromApi.setAttribute('backup-min', 1);
inputTextIntervalGetFromApi.setAttribute('backup-max', 100);
inputTextIntervalGetFromApi.setAttribute('backup-setting', 'intervalGetFromApi');
inputTextIntervalGetFromApi.addEventListener('blur', validateInputText);
labelIntervalGetFromApi.appendChild(document.createTextNode('最小更新间隔'));
labelIntervalGetFromApi.appendChild(inputTextIntervalGetFromApi);
labelIntervalGetFromApi.appendChild(document.createTextNode('小时'));
const divLabelEnableGetFromApiExtra = document.createElement('div');
divLabelEnableGetFromApiExtra.classList.add('backup-div-first' + 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) {
settings.enableGetThumbnails = false;
checkboxEnableGetThumbnails.checked = false;
divLabelEnableGetThumbnails.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelEnableGetThumbnails.classList.remove('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromApiExtra) {
divLabelIntervalGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableGetFromApiExtra.insertAdjacentElement('afterbegin', checkboxEnableGetFromApiExtra);
const divLabelEnableGetThumbnails = document.createElement('div');
divLabelEnableGetThumbnails.classList.add('backup-div-first' + classAppendNewFreshSpace, 'backup-advanced');
divLabelEnableGetThumbnails.setAttribute('title',
'默认: 关闭\n' +
'地址: https://api.bilibili.com/x/player/videoshot?aid={AV号}&cid={分集cid}\n' +
'数据: 进度条缩略图地址 (失效视频以及部分旧视频无法获取)\n' +
'如果UP主对某个视频进行了换源, 只要该视频的本地备份数据中保存了旧源的cid, 就可以尝试获取旧源的进度条缩略图地址。\n' +
'一次请求只能获取一个分集的进度条缩略图地址, 如果某个视频的分集较多, 则需要等待一段时间。');
divControls.appendChild(divLabelEnableGetThumbnails);
const labelEnableGetThumbnails = document.createElement('label');
labelEnableGetThumbnails.classList.add('backup-label' + classAppendNewFreshSpace);
labelEnableGetThumbnails.textContent = '获取进度条缩略图地址';
divLabelEnableGetThumbnails.appendChild(labelEnableGetThumbnails);
const checkboxEnableGetThumbnails = document.createElement('input');
checkboxEnableGetThumbnails.type = 'checkbox';
checkboxEnableGetThumbnails.checked = settings.enableGetThumbnails;
checkboxEnableGetThumbnails.addEventListener('change', () => {
try {
settings.enableGetThumbnails = checkboxEnableGetThumbnails.checked;
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableGetThumbnails.insertAdjacentElement('afterbegin', checkboxEnableGetThumbnails);
const divLabelEnableUpdateGetFromApiExtra = document.createElement('div');
divLabelEnableUpdateGetFromApiExtra.classList.add('backup-div-second' + classAppendNewFreshSpace, 'backup-advanced');
divLabelEnableUpdateGetFromApiExtra.setAttribute('title',
'默认: 开启');
divControls.appendChild(divLabelEnableUpdateGetFromApiExtra);
const labelEnableUpdateGetFromApiExtra = document.createElement('label');
labelEnableUpdateGetFromApiExtra.classList.add('backup-label' + classAppendNewFreshSpace);
labelEnableUpdateGetFromApiExtra.textContent = '启用更新';
divLabelEnableUpdateGetFromApiExtra.appendChild(labelEnableUpdateGetFromApiExtra);
const checkboxEnableUpdateGetFromApiExtra = document.createElement('input');
checkboxEnableUpdateGetFromApiExtra.type = 'checkbox';
checkboxEnableUpdateGetFromApiExtra.checked = settings.enableUpdateGetFromApiExtra;
checkboxEnableUpdateGetFromApiExtra.addEventListener('change', () => {
try {
settings.enableUpdateGetFromApiExtra = checkboxEnableUpdateGetFromApiExtra.checked;
if (!settings.enableUpdateGetFromApiExtra) {
divLabelIntervalGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelIntervalGetFromApiExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableUpdateGetFromApiExtra.insertAdjacentElement('afterbegin', checkboxEnableUpdateGetFromApiExtra);
const divLabelIntervalGetFromApiExtra = document.createElement('div');
divLabelIntervalGetFromApiExtra.classList.add('backup-div-second' + classAppendNewFreshSpace, 'backup-advanced');
divLabelIntervalGetFromApiExtra.setAttribute('title',
'默认: 5天');
divControls.appendChild(divLabelIntervalGetFromApiExtra);
const labelIntervalGetFromApiExtra = document.createElement('label');
labelIntervalGetFromApiExtra.classList.add('backup-label' + classAppendNewFreshSpace);
divLabelIntervalGetFromApiExtra.appendChild(labelIntervalGetFromApiExtra);
const inputTextIntervalGetFromApiExtra = document.createElement('input');
inputTextIntervalGetFromApiExtra.type = 'text';
inputTextIntervalGetFromApiExtra.classList.add('backup-inputText' + classAppendNewFreshSpace);
inputTextIntervalGetFromApiExtra.value = settings.intervalGetFromApiExtra;
inputTextIntervalGetFromApiExtra.setAttribute('backup-def', 5);
inputTextIntervalGetFromApiExtra.setAttribute('backup-min', 1);
inputTextIntervalGetFromApiExtra.setAttribute('backup-max', 100);
inputTextIntervalGetFromApiExtra.setAttribute('backup-setting', 'intervalGetFromApiExtra');
inputTextIntervalGetFromApiExtra.addEventListener('blur', validateInputText);
labelIntervalGetFromApiExtra.appendChild(document.createTextNode('最小更新间隔'));
labelIntervalGetFromApiExtra.appendChild(inputTextIntervalGetFromApiExtra);
labelIntervalGetFromApiExtra.appendChild(document.createTextNode('天'));
const divLabelEnableGetFromBiliplus = document.createElement('div');
divLabelEnableGetFromBiliplus.classList.add('backup-div-first' + 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) {
settings.enableGetFromBiliplusExtra = false;
checkboxEnableGetFromBiliplusExtra.checked = false;
divLabelEnableUpdateGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelEnableUpdateGetFromBiliplus.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromBiliplus) {
divLabelIntervalGetFromBiliplus.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
if (settings.enableGetFromApi) {
divLabelEnableGetFromBiliplusExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromBiliplusExtra) {
divLabelEnableUpdateGetFromBiliplusExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromBiliplusExtra) {
divLabelIntervalGetFromBiliplusExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
}
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableGetFromBiliplus.insertAdjacentElement('afterbegin', checkboxEnableGetFromBiliplus);
const divLabelEnableUpdateGetFromBiliplus = document.createElement('div');
divLabelEnableUpdateGetFromBiliplus.classList.add('backup-div-second' + classAppendNewFreshSpace, 'backup-advanced');
divLabelEnableUpdateGetFromBiliplus.setAttribute('title',
'默认: 关闭');
divControls.appendChild(divLabelEnableUpdateGetFromBiliplus);
const labelEnableUpdateGetFromBiliplus = document.createElement('label');
labelEnableUpdateGetFromBiliplus.classList.add('backup-label' + classAppendNewFreshSpace);
labelEnableUpdateGetFromBiliplus.textContent = '启用更新';
divLabelEnableUpdateGetFromBiliplus.appendChild(labelEnableUpdateGetFromBiliplus);
const checkboxEnableUpdateGetFromBiliplus = document.createElement('input');
checkboxEnableUpdateGetFromBiliplus.type = 'checkbox';
checkboxEnableUpdateGetFromBiliplus.checked = settings.enableUpdateGetFromBiliplus;
checkboxEnableUpdateGetFromBiliplus.addEventListener('change', () => {
try {
settings.enableUpdateGetFromBiliplus = checkboxEnableUpdateGetFromBiliplus.checked;
if (!settings.enableUpdateGetFromBiliplus) {
divLabelIntervalGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelIntervalGetFromBiliplus.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableUpdateGetFromBiliplus.insertAdjacentElement('afterbegin', checkboxEnableUpdateGetFromBiliplus);
const divLabelIntervalGetFromBiliplus = document.createElement('div');
divLabelIntervalGetFromBiliplus.classList.add('backup-div-second' + classAppendNewFreshSpace, 'backup-advanced');
divLabelIntervalGetFromBiliplus.setAttribute('title',
'默认: 10星期');
divControls.appendChild(divLabelIntervalGetFromBiliplus);
const labelIntervalGetFromBiliplus = document.createElement('label');
labelIntervalGetFromBiliplus.classList.add('backup-label' + classAppendNewFreshSpace);
divLabelIntervalGetFromBiliplus.appendChild(labelIntervalGetFromBiliplus);
const inputTextIntervalGetFromBiliplus = document.createElement('input');
inputTextIntervalGetFromBiliplus.type = 'text';
inputTextIntervalGetFromBiliplus.classList.add('backup-inputText' + classAppendNewFreshSpace);
inputTextIntervalGetFromBiliplus.value = settings.intervalGetFromBiliplus;
inputTextIntervalGetFromBiliplus.setAttribute('backup-def', 10);
inputTextIntervalGetFromBiliplus.setAttribute('backup-min', 1);
inputTextIntervalGetFromBiliplus.setAttribute('backup-max', 100);
inputTextIntervalGetFromBiliplus.setAttribute('backup-setting', 'intervalGetFromBiliplus');
inputTextIntervalGetFromBiliplus.addEventListener('blur', validateInputText);
labelIntervalGetFromBiliplus.appendChild(document.createTextNode('最小更新间隔'));
labelIntervalGetFromBiliplus.appendChild(inputTextIntervalGetFromBiliplus);
labelIntervalGetFromBiliplus.appendChild(document.createTextNode('星期'));
const divLabelEnableGetFromBiliplusExtra = document.createElement('div');
divLabelEnableGetFromBiliplusExtra.classList.add('backup-div-first' + classAppendNewFreshSpace, 'backup-advanced');
divLabelEnableGetFromBiliplusExtra.setAttribute('title',
'默认: 关闭\n' +
'地址: https://www.biliplus.com/all/video/av{AV号}/\n' +
'数据: 调用下面的接口所需的验证参数\n' +
'地址: https://www.biliplus.com/api/view_all?av={AV号}&ts={验证参数1}&sign={验证参数2}\n' +
'数据: 标题, 简介, 封面地址, UP主昵称 (第一次备份到BiliPlus时的版本); 每个分集的标题, cid (所有曾经备份到BiliPlus版本)\n' +
'BiliPlus原始页面的底部有一个刷新数据的功能, 该功能会让BiliPlus再次从B站接口获取某个视频的最新信息并保存在其数据库中。\n' +
'BiliPlus原始页面显示的信息为最后一次备份到BiliPlus时的版本, 而此接口可以获取到之前备份到BiliPlus时的版本。\n' +
'请注意: 此接口有调用频率限制, 平均每分钟不能超过5次, 否则会出现请求失败的情况。\n' +
'在脚本从BiliPlus获取了当前页所有视频的额外数据之后, 继续从BiliPlus获取下一页所有视频的额外数据之前, 如果您使用的是新版个人空间, 请至少等待360秒; 如果是旧版个人空间, 请至少等待180秒。');
divControls.appendChild(divLabelEnableGetFromBiliplusExtra);
const labelEnableGetFromBiliplusExtra = document.createElement('label');
labelEnableGetFromBiliplusExtra.classList.add('backup-label' + classAppendNewFreshSpace);
labelEnableGetFromBiliplusExtra.textContent = '从BiliPlus获取额外数据(频率受限)';
divLabelEnableGetFromBiliplusExtra.appendChild(labelEnableGetFromBiliplusExtra);
const checkboxEnableGetFromBiliplusExtra = document.createElement('input');
checkboxEnableGetFromBiliplusExtra.type = 'checkbox';
checkboxEnableGetFromBiliplusExtra.checked = settings.enableGetFromBiliplusExtra;
checkboxEnableGetFromBiliplusExtra.addEventListener('change', () => {
try {
settings.enableGetFromBiliplusExtra = checkboxEnableGetFromBiliplusExtra.checked;
if (!settings.enableGetFromBiliplusExtra) {
divLabelEnableUpdateGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelEnableUpdateGetFromBiliplusExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromBiliplusExtra) {
divLabelIntervalGetFromBiliplusExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableGetFromBiliplusExtra.insertAdjacentElement('afterbegin', checkboxEnableGetFromBiliplusExtra);
const divLabelEnableUpdateGetFromBiliplusExtra = document.createElement('div');
divLabelEnableUpdateGetFromBiliplusExtra.classList.add('backup-div-second' + classAppendNewFreshSpace, 'backup-advanced');
divLabelEnableUpdateGetFromBiliplusExtra.setAttribute('title',
'默认: 关闭');
divControls.appendChild(divLabelEnableUpdateGetFromBiliplusExtra);
const labelEnableUpdateGetFromBiliplusExtra = document.createElement('label');
labelEnableUpdateGetFromBiliplusExtra.classList.add('backup-label' + classAppendNewFreshSpace);
labelEnableUpdateGetFromBiliplusExtra.textContent = '启用更新';
divLabelEnableUpdateGetFromBiliplusExtra.appendChild(labelEnableUpdateGetFromBiliplusExtra);
const checkboxEnableUpdateGetFromBiliplusExtra = document.createElement('input');
checkboxEnableUpdateGetFromBiliplusExtra.type = 'checkbox';
checkboxEnableUpdateGetFromBiliplusExtra.checked = settings.enableUpdateGetFromBiliplusExtra;
checkboxEnableUpdateGetFromBiliplusExtra.addEventListener('change', () => {
try {
settings.enableUpdateGetFromBiliplusExtra = checkboxEnableUpdateGetFromBiliplusExtra.checked;
if (!settings.enableUpdateGetFromBiliplusExtra) {
divLabelIntervalGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelIntervalGetFromBiliplusExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableUpdateGetFromBiliplusExtra.insertAdjacentElement('afterbegin', checkboxEnableUpdateGetFromBiliplusExtra);
const divLabelIntervalGetFromBiliplusExtra = document.createElement('div');
divLabelIntervalGetFromBiliplusExtra.classList.add('backup-div-second' + classAppendNewFreshSpace, 'backup-advanced');
divLabelIntervalGetFromBiliplusExtra.setAttribute('title',
'默认: 10星期');
divControls.appendChild(divLabelIntervalGetFromBiliplusExtra);
const labelIntervalGetFromBiliplusExtra = document.createElement('label');
labelIntervalGetFromBiliplusExtra.classList.add('backup-label' + classAppendNewFreshSpace);
divLabelIntervalGetFromBiliplusExtra.appendChild(labelIntervalGetFromBiliplusExtra);
const inputTextIntervalGetFromBiliplusExtra = document.createElement('input');
inputTextIntervalGetFromBiliplusExtra.type = 'text';
inputTextIntervalGetFromBiliplusExtra.classList.add('backup-inputText' + classAppendNewFreshSpace);
inputTextIntervalGetFromBiliplusExtra.value = settings.intervalGetFromBiliplusExtra;
inputTextIntervalGetFromBiliplusExtra.setAttribute('backup-def', 10);
inputTextIntervalGetFromBiliplusExtra.setAttribute('backup-min', 1);
inputTextIntervalGetFromBiliplusExtra.setAttribute('backup-max', 100);
inputTextIntervalGetFromBiliplusExtra.setAttribute('backup-setting', 'intervalGetFromBiliplusExtra');
inputTextIntervalGetFromBiliplusExtra.addEventListener('blur', validateInputText);
labelIntervalGetFromBiliplusExtra.appendChild(document.createTextNode('最小更新间隔'));
labelIntervalGetFromBiliplusExtra.appendChild(inputTextIntervalGetFromBiliplusExtra);
labelIntervalGetFromBiliplusExtra.appendChild(document.createTextNode('星期'));
const divLabelEnableGetFromJijidown = document.createElement('div');
divLabelEnableGetFromJijidown.classList.add('backup-div-first' + 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;
divLabelEnableUpdateGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL1.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL2.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelEnableUpdateGetFromJijidown.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromJijidown) {
divLabelIntervalGetFromJijidown.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divLabelEnableGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableGetFromJijidownExtra) {
divLabelEnableUpdateGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromJijidownExtra) {
divLabelIntervalGetFromJijidownExtra.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 divLabelEnableUpdateGetFromJijidown = document.createElement('div');
divLabelEnableUpdateGetFromJijidown.classList.add('backup-div-second' + classAppendNewFreshSpace, 'backup-advanced');
divLabelEnableUpdateGetFromJijidown.setAttribute('title',
'默认: 关闭');
divControls.appendChild(divLabelEnableUpdateGetFromJijidown);
const labelEnableUpdateGetFromJijidown = document.createElement('label');
labelEnableUpdateGetFromJijidown.classList.add('backup-label' + classAppendNewFreshSpace);
labelEnableUpdateGetFromJijidown.textContent = '启用更新';
divLabelEnableUpdateGetFromJijidown.appendChild(labelEnableUpdateGetFromJijidown);
const checkboxEnableUpdateGetFromJijidown = document.createElement('input');
checkboxEnableUpdateGetFromJijidown.type = 'checkbox';
checkboxEnableUpdateGetFromJijidown.checked = settings.enableUpdateGetFromJijidown;
checkboxEnableUpdateGetFromJijidown.addEventListener('change', () => {
try {
settings.enableUpdateGetFromJijidown = checkboxEnableUpdateGetFromJijidown.checked;
if (!settings.enableUpdateGetFromJijidown) {
divLabelIntervalGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelIntervalGetFromJijidown.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableUpdateGetFromJijidown.insertAdjacentElement('afterbegin', checkboxEnableUpdateGetFromJijidown);
const divLabelIntervalGetFromJijidown = document.createElement('div');
divLabelIntervalGetFromJijidown.classList.add('backup-div-second' + classAppendNewFreshSpace, 'backup-advanced');
divLabelIntervalGetFromJijidown.setAttribute('title',
'默认: 10星期');
divControls.appendChild(divLabelIntervalGetFromJijidown);
const labelIntervalGetFromJijidown = document.createElement('label');
labelIntervalGetFromJijidown.classList.add('backup-label' + classAppendNewFreshSpace);
divLabelIntervalGetFromJijidown.appendChild(labelIntervalGetFromJijidown);
const inputTextIntervalGetFromJijidown = document.createElement('input');
inputTextIntervalGetFromJijidown.type = 'text';
inputTextIntervalGetFromJijidown.classList.add('backup-inputText' + classAppendNewFreshSpace);
inputTextIntervalGetFromJijidown.value = settings.intervalGetFromJijidown;
inputTextIntervalGetFromJijidown.setAttribute('backup-def', 10);
inputTextIntervalGetFromJijidown.setAttribute('backup-min', 1);
inputTextIntervalGetFromJijidown.setAttribute('backup-max', 100);
inputTextIntervalGetFromJijidown.setAttribute('backup-setting', 'intervalGetFromJijidown');
inputTextIntervalGetFromJijidown.addEventListener('blur', validateInputText);
labelIntervalGetFromJijidown.appendChild(document.createTextNode('最小更新间隔'));
labelIntervalGetFromJijidown.appendChild(inputTextIntervalGetFromJijidown);
labelIntervalGetFromJijidown.appendChild(document.createTextNode('星期'));
const divLabelEnableGetFromJijidownExtra = document.createElement('div');
divLabelEnableGetFromJijidownExtra.classList.add('backup-div-first' + classAppendNewFreshSpace, 'backup-advanced');
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) {
divLabelEnableUpdateGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelEnableUpdateGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromJijidownExtra) {
divLabelIntervalGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableGetFromJijidownExtra.insertAdjacentElement('afterbegin', checkboxEnableGetFromJijidownExtra);
const divLabelEnableUpdateGetFromJijidownExtra = document.createElement('div');
divLabelEnableUpdateGetFromJijidownExtra.classList.add('backup-div-second' + classAppendNewFreshSpace, 'backup-advanced');
divLabelEnableUpdateGetFromJijidownExtra.setAttribute('title',
'默认: 关闭');
divControls.appendChild(divLabelEnableUpdateGetFromJijidownExtra);
const labelEnableUpdateGetFromJijidownExtra = document.createElement('label');
labelEnableUpdateGetFromJijidownExtra.classList.add('backup-label' + classAppendNewFreshSpace);
labelEnableUpdateGetFromJijidownExtra.textContent = '启用更新';
divLabelEnableUpdateGetFromJijidownExtra.appendChild(labelEnableUpdateGetFromJijidownExtra);
const checkboxEnableUpdateGetFromJijidownExtra = document.createElement('input');
checkboxEnableUpdateGetFromJijidownExtra.type = 'checkbox';
checkboxEnableUpdateGetFromJijidownExtra.checked = settings.enableUpdateGetFromJijidownExtra;
checkboxEnableUpdateGetFromJijidownExtra.addEventListener('change', () => {
try {
settings.enableUpdateGetFromJijidownExtra = checkboxEnableUpdateGetFromJijidownExtra.checked;
if (!settings.enableUpdateGetFromJijidownExtra) {
divLabelIntervalGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelIntervalGetFromJijidownExtra.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableUpdateGetFromJijidownExtra.insertAdjacentElement('afterbegin', checkboxEnableUpdateGetFromJijidownExtra);
const divLabelIntervalGetFromJijidownExtra = document.createElement('div');
divLabelIntervalGetFromJijidownExtra.classList.add('backup-div-second' + classAppendNewFreshSpace, 'backup-advanced');
divLabelIntervalGetFromJijidownExtra.setAttribute('title',
'默认: 10星期');
divControls.appendChild(divLabelIntervalGetFromJijidownExtra);
const labelIntervalGetFromJijidownExtra = document.createElement('label');
labelIntervalGetFromJijidownExtra.classList.add('backup-label' + classAppendNewFreshSpace);
divLabelIntervalGetFromJijidownExtra.appendChild(labelIntervalGetFromJijidownExtra);
const inputTextIntervalGetFromJijidownExtra = document.createElement('input');
inputTextIntervalGetFromJijidownExtra.type = 'text';
inputTextIntervalGetFromJijidownExtra.classList.add('backup-inputText' + classAppendNewFreshSpace);
inputTextIntervalGetFromJijidownExtra.value = settings.intervalGetFromJijidownExtra;
inputTextIntervalGetFromJijidownExtra.setAttribute('backup-def', 10);
inputTextIntervalGetFromJijidownExtra.setAttribute('backup-min', 1);
inputTextIntervalGetFromJijidownExtra.setAttribute('backup-max', 100);
inputTextIntervalGetFromJijidownExtra.setAttribute('backup-setting', 'intervalGetFromJijidownExtra');
inputTextIntervalGetFromJijidownExtra.addEventListener('blur', validateInputText);
labelIntervalGetFromJijidownExtra.appendChild(document.createTextNode('最小更新间隔'));
labelIntervalGetFromJijidownExtra.appendChild(inputTextIntervalGetFromJijidownExtra);
labelIntervalGetFromJijidownExtra.appendChild(document.createTextNode('星期'));
const divSwitchGetFromJijidownURL1 = document.createElement('div');
divSwitchGetFromJijidownURL1.classList.add('backup-div-second' + 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';
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-second' + 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';
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-first' + 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;
if (!settings.enableGetFromXbeibeix) {
divLabelEnableUpdateGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL1.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL2.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelEnableUpdateGetFromXbeibeix.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (settings.enableUpdateGetFromXbeibeix) {
divLabelIntervalGetFromXbeibeix.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
divSwitchGetFromXbeibeixURL1.classList.remove('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL2.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableGetFromXbeibeix.insertAdjacentElement('afterbegin', checkboxEnableGetFromXbeibeix);
const divLabelEnableUpdateGetFromXbeibeix = document.createElement('div');
divLabelEnableUpdateGetFromXbeibeix.classList.add('backup-div-second' + classAppendNewFreshSpace, 'backup-advanced');
divLabelEnableUpdateGetFromXbeibeix.setAttribute('title',
'默认: 关闭');
divControls.appendChild(divLabelEnableUpdateGetFromXbeibeix);
const labelEnableUpdateGetFromXbeibeix = document.createElement('label');
labelEnableUpdateGetFromXbeibeix.classList.add('backup-label' + classAppendNewFreshSpace);
labelEnableUpdateGetFromXbeibeix.textContent = '启用更新';
divLabelEnableUpdateGetFromXbeibeix.appendChild(labelEnableUpdateGetFromXbeibeix);
const checkboxEnableUpdateGetFromXbeibeix = document.createElement('input');
checkboxEnableUpdateGetFromXbeibeix.type = 'checkbox';
checkboxEnableUpdateGetFromXbeibeix.checked = settings.enableUpdateGetFromXbeibeix;
checkboxEnableUpdateGetFromXbeibeix.addEventListener('change', () => {
try {
settings.enableUpdateGetFromXbeibeix = checkboxEnableUpdateGetFromXbeibeix.checked;
if (!settings.enableUpdateGetFromXbeibeix) {
divLabelIntervalGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
divLabelIntervalGetFromXbeibeix.classList.remove('backup-disabled' + classAppendNewFreshSpace);
}
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelEnableUpdateGetFromXbeibeix.insertAdjacentElement('afterbegin', checkboxEnableUpdateGetFromXbeibeix);
const divLabelIntervalGetFromXbeibeix = document.createElement('div');
divLabelIntervalGetFromXbeibeix.classList.add('backup-div-second' + classAppendNewFreshSpace, 'backup-advanced');
divLabelIntervalGetFromXbeibeix.setAttribute('title',
'默认: 10星期');
divControls.appendChild(divLabelIntervalGetFromXbeibeix);
const labelIntervalGetFromXbeibeix = document.createElement('label');
labelIntervalGetFromXbeibeix.classList.add('backup-label' + classAppendNewFreshSpace);
divLabelIntervalGetFromXbeibeix.appendChild(labelIntervalGetFromXbeibeix);
const inputTextIntervalGetFromXbeibeix = document.createElement('input');
inputTextIntervalGetFromXbeibeix.type = 'text';
inputTextIntervalGetFromXbeibeix.classList.add('backup-inputText' + classAppendNewFreshSpace);
inputTextIntervalGetFromXbeibeix.value = settings.intervalGetFromXbeibeix;
inputTextIntervalGetFromXbeibeix.setAttribute('backup-def', 10);
inputTextIntervalGetFromXbeibeix.setAttribute('backup-min', 1);
inputTextIntervalGetFromXbeibeix.setAttribute('backup-max', 100);
inputTextIntervalGetFromXbeibeix.setAttribute('backup-setting', 'intervalGetFromXbeibeix');
inputTextIntervalGetFromXbeibeix.addEventListener('blur', validateInputText);
labelIntervalGetFromXbeibeix.appendChild(document.createTextNode('最小更新间隔'));
labelIntervalGetFromXbeibeix.appendChild(inputTextIntervalGetFromXbeibeix);
labelIntervalGetFromXbeibeix.appendChild(document.createTextNode('星期'));
const divSwitchGetFromXbeibeixURL1 = document.createElement('div');
divSwitchGetFromXbeibeixURL1.classList.add('backup-div-second' + 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';
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-second' + 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';
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) {
divLabelEnableAutoNextFavlist.classList.remove('backup-disabled' + classAppendNewFreshSpace);
if (!activeControllers.size) {
if (newFreshSpace) {
if (!document.querySelector('div.fav-collapse').contains(document.querySelector('div.vui_sidebar-item--active'))) {
return;
}
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 {
if (!document.querySelector('div.nav-container').contains(document.querySelector('.fav-item.cur'))) {
return;
}
const pager = document.querySelector('li.be-pager-next');
if (pager && !pager.classList.contains('be-pager-disabled')) {
await delay(500);
if (enableAutoNextPage) {
pager.click();
}
}
}
}
} else {
enableAutoNextFavlist = false;
checkboxEnableAutoNextFavlist.checked = false;
divLabelEnableAutoNextFavlist.classList.add('backup-disabled' + classAppendNewFreshSpace);
}
} catch (error) {
catchUnknownError(error);
}
});
labelEnableAutoNextPage.insertAdjacentElement('afterbegin', checkboxEnableAutoNextPage);
const divLabelEnableAutoNextFavlist = document.createElement('div');
divLabelEnableAutoNextFavlist.classList.add('backup-div-first' + classAppendNewFreshSpace, 'backup-disabled' + classAppendNewFreshSpace);
divLabelEnableAutoNextFavlist.setAttribute('title',
'开启后脚本将在当前收藏夹的视频都处理完毕之后点击下一收藏夹, 继续处理下一收藏夹的视频。');
divControls.appendChild(divLabelEnableAutoNextFavlist);
const labelEnableAutoNextFavlist = document.createElement('label');
labelEnableAutoNextFavlist.classList.add('backup-label' + classAppendNewFreshSpace);
labelEnableAutoNextFavlist.textContent = '自动点击下一收藏夹';
divLabelEnableAutoNextFavlist.appendChild(labelEnableAutoNextFavlist);
const checkboxEnableAutoNextFavlist = document.createElement('input');
checkboxEnableAutoNextFavlist.type = 'checkbox';
checkboxEnableAutoNextFavlist.checked = enableAutoNextFavlist;
checkboxEnableAutoNextFavlist.addEventListener('change', async () => {
try {
enableAutoNextFavlist = checkboxEnableAutoNextFavlist.checked;
if (enableAutoNextFavlist && !activeControllers.size) {
let currentFavlist;
if (newFreshSpace) {
currentFavlist = document.querySelector('div.vui_sidebar-item--active');
if (!document.querySelector('div.fav-collapse').contains(currentFavlist)) {
return;
}
const pager = Array.from(document.querySelectorAll('button.vui_pagenation--btn-side')).find(el => el.innerText === '下一页');
if (pager && !pager.classList.contains('vui_button--disabled')) {
} else {
if (!currentFavlist.parentNode.getAttribute('id')) {
if (document.querySelector('div.fav-sortable-list').childElementCount) {
await delay(500);
if (enableAutoNextFavlist) {
document.querySelector('div.fav-sortable-list').firstElementChild.querySelector('div').click();
}
}
} else {
const nextFavlist = currentFavlist.parentNode.nextElementSibling;
if (nextFavlist) {
await delay(500);
if (enableAutoNextFavlist) {
nextFavlist.querySelector('div').click();
}
}
}
}
} else {
currentFavlist = document.querySelector('.fav-item.cur');
if (!document.querySelector('div.nav-container').contains(currentFavlist)) {
return;
}
const pager = document.querySelector('li.be-pager-next');
if (pager && !pager.classList.contains('be-pager-disabled')) {
} else {
if (currentFavlist.nodeName === 'DIV') {
if (document.querySelector('ul.fav-list').childElementCount) {
await delay(500);
if (enableAutoNextFavlist) {
document.querySelector('ul.fav-list').firstElementChild.querySelector('a').click();
}
}
} else {
const nextFavlist = currentFavlist.nextElementSibling;
if (nextFavlist) {
await delay(500);
if (enableAutoNextFavlist) {
nextFavlist.querySelector('a').click();
}
}
}
}
}
}
} catch (error) {
catchUnknownError(error);
}
});
labelEnableAutoNextFavlist.insertAdjacentElement('afterbegin', checkboxEnableAutoNextFavlist);
const divLabelIntervalAutoNextPage = document.createElement('div');
divLabelIntervalAutoNextPage.classList.add('backup-div-second' + classAppendNewFreshSpace, 'backup-advanced');
divLabelIntervalAutoNextPage.setAttribute('title',
'默认: 5秒\n' +
'每次点击下一页或下一收藏夹之前停留在当前页的时间。');
divControls.appendChild(divLabelIntervalAutoNextPage);
const labelIntervalAutoNextPage = document.createElement('label');
labelIntervalAutoNextPage.classList.add('backup-label' + classAppendNewFreshSpace);
divLabelIntervalAutoNextPage.appendChild(labelIntervalAutoNextPage);
const inputTextIntervalAutoNextPage = document.createElement('input');
inputTextIntervalAutoNextPage.type = 'text';
inputTextIntervalAutoNextPage.classList.add('backup-inputText' + classAppendNewFreshSpace);
inputTextIntervalAutoNextPage.value = settings.intervalAutoNextPage;
inputTextIntervalAutoNextPage.setAttribute('backup-def', 5);
inputTextIntervalAutoNextPage.setAttribute('backup-min', 1);
inputTextIntervalAutoNextPage.setAttribute('backup-max', 500);
inputTextIntervalAutoNextPage.setAttribute('backup-setting', 'intervalAutoNextPage');
inputTextIntervalAutoNextPage.addEventListener('blur', validateInputText);
labelIntervalAutoNextPage.appendChild(document.createTextNode('停留间隔'));
labelIntervalAutoNextPage.appendChild(inputTextIntervalAutoNextPage);
labelIntervalAutoNextPage.appendChild(document.createTextNode('秒'));
const divLabelRequestTimeout = document.createElement('div');
divLabelRequestTimeout.classList.add('backup-div-first' + classAppendNewFreshSpace, 'backup-advanced');
divLabelRequestTimeout.setAttribute('title',
'默认: 10秒\n' +
'脚本获取数据时, 如果等待了设定的时长后仍未得到响应数据, 则暂时跳过处理当前视频。');
divControls.appendChild(divLabelRequestTimeout);
const labelRequestTimeout = document.createElement('label');
labelRequestTimeout.classList.add('backup-label' + classAppendNewFreshSpace);
divLabelRequestTimeout.appendChild(labelRequestTimeout);
const inputTextRequestTimeout = document.createElement('input');
inputTextRequestTimeout.type = 'text';
inputTextRequestTimeout.classList.add('backup-inputText' + classAppendNewFreshSpace);
inputTextRequestTimeout.value = settings.requestTimeout;
inputTextRequestTimeout.setAttribute('backup-def', 10);
inputTextRequestTimeout.setAttribute('backup-min', 1);
inputTextRequestTimeout.setAttribute('backup-max', 100);
inputTextRequestTimeout.setAttribute('backup-setting', 'requestTimeout');
inputTextRequestTimeout.addEventListener('blur', validateInputText);
labelRequestTimeout.appendChild(document.createTextNode('请求超时时间'));
labelRequestTimeout.appendChild(inputTextRequestTimeout);
labelRequestTimeout.appendChild(document.createTextNode('秒'));
const divDelayBeforeMain = document.createElement('div');
divDelayBeforeMain.classList.add('backup-div-first' + classAppendNewFreshSpace, 'backup-advanced');
divDelayBeforeMain.setAttribute('title',
'默认: 300毫秒\n' +
'如果您使用的是新版个人空间, 并且遇到了视频标题下方的信息展示出来后又突然消失的情况, 请将这个时长调大一些。');
divControls.appendChild(divDelayBeforeMain);
const labelDelayBeforeMain = document.createElement('label');
labelDelayBeforeMain.classList.add('backup-label' + classAppendNewFreshSpace);
divDelayBeforeMain.appendChild(labelDelayBeforeMain);
const inputTextDelayBeforeMain = document.createElement('input');
inputTextDelayBeforeMain.type = 'text';
inputTextDelayBeforeMain.classList.add('backup-inputText' + classAppendNewFreshSpace);
inputTextDelayBeforeMain.value = settings.delayBeforeMain;
inputTextDelayBeforeMain.setAttribute('backup-def', 300);
inputTextDelayBeforeMain.setAttribute('backup-min', 50);
inputTextDelayBeforeMain.setAttribute('backup-max', 1000);
inputTextDelayBeforeMain.setAttribute('backup-setting', 'delayBeforeMain');
inputTextDelayBeforeMain.addEventListener('blur', validateInputText);
labelDelayBeforeMain.appendChild(document.createTextNode('开始处理视频前等待'));
labelDelayBeforeMain.appendChild(inputTextDelayBeforeMain);
labelDelayBeforeMain.appendChild(document.createTextNode('毫秒'));
const divLabelAppendDropdownCover = document.createElement('div');
divLabelAppendDropdownCover.classList.add('backup-div-first' + classAppendNewFreshSpace, 'backup-advanced');
divLabelAppendDropdownCover.setAttribute('title',
'默认: 开启\n' +
'控制是否在各个视频右下角的下拉列表中添加查看封面原图的功能。');
divControls.appendChild(divLabelAppendDropdownCover);
const labelAppendDropdownCover = document.createElement('label');
labelAppendDropdownCover.classList.add('backup-label' + classAppendNewFreshSpace);
labelAppendDropdownCover.textContent = '下拉列表: 封面原图';
divLabelAppendDropdownCover.appendChild(labelAppendDropdownCover);
const checkboxAppendDropdownCover = document.createElement('input');
checkboxAppendDropdownCover.type = 'checkbox';
checkboxAppendDropdownCover.checked = settings.appendDropdownCover;
checkboxAppendDropdownCover.addEventListener('change', () => {
try {
settings.appendDropdownCover = checkboxAppendDropdownCover.checked;
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelAppendDropdownCover.insertAdjacentElement('afterbegin', checkboxAppendDropdownCover);
const divLabelAppendDropdownLocal = document.createElement('div');
divLabelAppendDropdownLocal.classList.add('backup-div-first' + classAppendNewFreshSpace, 'backup-advanced');
divLabelAppendDropdownLocal.setAttribute('title',
'默认: 开启');
divControls.appendChild(divLabelAppendDropdownLocal);
const labelAppendDropdownLocal = document.createElement('label');
labelAppendDropdownLocal.classList.add('backup-label' + classAppendNewFreshSpace);
labelAppendDropdownLocal.textContent = '下拉列表: 本地备份数据';
divLabelAppendDropdownLocal.appendChild(labelAppendDropdownLocal);
const checkboxAppendDropdownLocal = document.createElement('input');
checkboxAppendDropdownLocal.type = 'checkbox';
checkboxAppendDropdownLocal.checked = settings.appendDropdownLocal;
checkboxAppendDropdownLocal.addEventListener('change', () => {
try {
settings.appendDropdownLocal = checkboxAppendDropdownLocal.checked;
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelAppendDropdownLocal.insertAdjacentElement('afterbegin', checkboxAppendDropdownLocal);
const divLabelAppendDropdownJump = document.createElement('div');
divLabelAppendDropdownJump.classList.add('backup-div-first' + classAppendNewFreshSpace, 'backup-advanced');
divLabelAppendDropdownJump.setAttribute('title',
'默认: 开启');
divControls.appendChild(divLabelAppendDropdownJump);
const labelAppendDropdownJump = document.createElement('label');
labelAppendDropdownJump.classList.add('backup-label' + classAppendNewFreshSpace);
labelAppendDropdownJump.textContent = '下拉列表: 跳转至BJX';
divLabelAppendDropdownJump.appendChild(labelAppendDropdownJump);
const checkboxAppendDropdownJump = document.createElement('input');
checkboxAppendDropdownJump.type = 'checkbox';
checkboxAppendDropdownJump.checked = settings.appendDropdownJump;
checkboxAppendDropdownJump.addEventListener('change', () => {
try {
settings.appendDropdownJump = checkboxAppendDropdownJump.checked;
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelAppendDropdownJump.insertAdjacentElement('afterbegin', checkboxAppendDropdownJump);
const divLabelAppendDropdownReset = document.createElement('div');
divLabelAppendDropdownReset.classList.add('backup-div-first' + classAppendNewFreshSpace, 'backup-advanced');
divLabelAppendDropdownReset.setAttribute('title',
'默认: 开启');
divControls.appendChild(divLabelAppendDropdownReset);
const labelAppendDropdownReset = document.createElement('label');
labelAppendDropdownReset.classList.add('backup-label' + classAppendNewFreshSpace);
labelAppendDropdownReset.textContent = '下拉列表: 重置备份数据';
divLabelAppendDropdownReset.appendChild(labelAppendDropdownReset);
const checkboxAppendDropdownReset = document.createElement('input');
checkboxAppendDropdownReset.type = 'checkbox';
checkboxAppendDropdownReset.checked = settings.appendDropdownReset;
checkboxAppendDropdownReset.addEventListener('change', () => {
try {
settings.appendDropdownReset = checkboxAppendDropdownReset.checked;
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelAppendDropdownReset.insertAdjacentElement('afterbegin', checkboxAppendDropdownReset);
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 = '显示高级选项和功能';
divLabelDisplayAdvancedControls.appendChild(labelDisplayAdvancedControls);
const checkboxDisplayAdvancedControls = document.createElement('input');
checkboxDisplayAdvancedControls.type = 'checkbox';
checkboxDisplayAdvancedControls.checked = settings.displayAdvancedControls;
checkboxDisplayAdvancedControls.addEventListener('change', () => {
try {
settings.displayAdvancedControls = checkboxDisplayAdvancedControls.checked;
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) });
}
GM_setValue('settings', settings);
} 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 currentTs = getCurrentTs();
// 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(currentTs)}.json`;
link.click();
URL.revokeObjectURL(link.href);
if (settings.exportBackupWithoutTsFrom) {
removeTsFromInBackup(backupsToExport);
// 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(currentTs)}_without_ts_from.json`;
link.click();
URL.revokeObjectURL(link.href);
}
} catch (error) {
catchUnknownError(error);
}
});
divButtonExportBackup.appendChild(buttonExportBackup);
const divLabelExportBackupWithoutTsFrom = document.createElement('div');
divLabelExportBackupWithoutTsFrom.classList.add('backup-div-first' + classAppendNewFreshSpace, 'backup-advanced');
divLabelExportBackupWithoutTsFrom.setAttribute('title',
'默认: 关闭\n' +
'本地备份数据中各个信息的ts代表上一次从B站接口获取到该信息的时间戳或第三方网站备份该信息的时间戳, from代表该信息的获取来源。\n' +
'如果您想要对比两个备份数据文件内容的差异, 对比两个文件去除ts和from的副本会更容易一些。\n' +
'导入本地备份数据时请导入原始文件, 不要导入去除ts和from的副本。');
divControls.appendChild(divLabelExportBackupWithoutTsFrom);
const labelExportBackupWithoutTsFrom = document.createElement('label');
labelExportBackupWithoutTsFrom.classList.add('backup-label' + classAppendNewFreshSpace);
labelExportBackupWithoutTsFrom.textContent = '同时导出去除ts和from的副本';
divLabelExportBackupWithoutTsFrom.appendChild(labelExportBackupWithoutTsFrom);
const checkboxExportBackupWithoutTsFrom = document.createElement('input');
checkboxExportBackupWithoutTsFrom.type = 'checkbox';
checkboxExportBackupWithoutTsFrom.checked = settings.exportBackupWithoutTsFrom;
checkboxExportBackupWithoutTsFrom.addEventListener('change', () => {
try {
settings.exportBackupWithoutTsFrom = checkboxExportBackupWithoutTsFrom.checked;
GM_setValue('settings', settings);
} catch (error) {
catchUnknownError(error);
}
});
labelExportBackupWithoutTsFrom.insertAdjacentElement('afterbegin', checkboxExportBackupWithoutTsFrom);
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';
inputFile.accept = '.json';
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.r###lt);
if (typeof backupsToImport !== 'object') {
addMessage('文件内容有误, 无法导入', false, true);
return;
}
for (const BVOfBackupToImport in backupsToImport) {
const backupToImport = backupsToImport[BVOfBackupToImport];
try {
formatBackup(backupToImport, false, undefined);
const backup = GM_getValue(BVOfBackupToImport, {
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,
biliplusExtra: null,
jijidown: null,
jijidownExtra: null,
xbeibeix: null,
});
formatBackup(backup, false, undefined);
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.thumbnails, el.cid, el.ts, el.from);
});
}
['api', 'apiExtra', 'biliplus', 'biliplusExtra', '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(BVOfBackupToImport, sortedBackup);
} catch (error) {
addMessage('导入该视频失败', false, true);
addMessage(`BV号: ${BVOfBackupToImport}`, 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);
console.error('本地已有的数据');
console.error(GM_getValue(BVOfBackupToImport, {}));
}
}
addMessage('导入完成');
} catch (error) {
catchUnknownError(error);
}
};
reader.readAsText(file);
} catch (error) {
catchUnknownError(error);
}
});
const divButtonGetFromApiLegacy = document.createElement('div');
divButtonGetFromApiLegacy.classList.add('backup-div-first' + classAppendNewFreshSpace, 'backup-advanced');
divButtonGetFromApiLegacy.setAttribute('title',
'地址: https://api.bilibili.com/medialist/gateway/base/spaceDetail?media_id={收藏夹fid}&pn={页码}&ps={每页展示视频数量}\n' +
'数据: AV号, 标题 (失效视频无法获取), 简介 (仅能获取前255个字符), 封面地址 (失效视频无法获取), UP主UID, UP主昵称, UP主头像地址, 上传时间, 发布时间, 添加到当前收藏夹的时间, 每个分集的标题, cid (均为最新版本)\n' +
'此功能将会从旧版B站接口获取当前收藏夹内所有视频的数据。与目前的B站接口相比, 旧版接口可以获取到每个分集的标题和cid, 无论视频是否失效。\n' +
'您需要将当前收藏夹设置为公开后才能获取到数据。如果收藏夹内第一个视频不是失效视频, 修改可见性会导致收藏夹的封面被固定为该视频的封面, 建议修改可见性之前先复制一个失效视频到当前收藏夹的首位。');
divControls.appendChild(divButtonGetFromApiLegacy);
const buttonGetFromApiLegacy = document.createElement('button');
buttonGetFromApiLegacy.type = 'button';
buttonGetFromApiLegacy.classList.add('backup-button' + classAppendNewFreshSpace);
buttonGetFromApiLegacy.textContent = '从旧版B站接口获取数据';
buttonGetFromApiLegacy.addEventListener('click', async () => {
try {
clearMessage();
let currentFavlist;
if (newFreshSpace) {
currentFavlist = document.querySelector('div.vui_sidebar-item--active');
if (!document.querySelector('div.fav-collapse').contains(currentFavlist)) {
throw ['不支持处理特殊收藏夹'];
}
} else {
currentFavlist = document.querySelector('.fav-item.cur');
if (!document.querySelector('div.nav-container').contains(currentFavlist)) {
throw ['不支持处理特殊收藏夹'];
}
}
let fid;
if (newFreshSpace) {
const getFidFromURLMatch = location.href.match(getFidFromURLRegex);
if (getFidFromURLMatch) {
fid = parseInt(getFidFromURLMatch[1], 10);
} else if (settings.defaultFavlistFid) {
fid = settings.defaultFavlistFid;
} else {
throw ['无法获取当前收藏夹的fid, 刷新页面可能有帮助'];
}
} else {
fid = parseInt(currentFavlist.getAttribute('fid'), 10);
}
let pageNumber = 1;
let count = 0;
while (true) {
const response = await new Promise((resolve, reject) => {
GM.xmlHttpRequest({
method: 'GET',
url: `https://api.bilibili.com/medialist/gateway/base/spaceDetail?media_id=${fid}&pn=${pageNumber}&ps=20&keyword=&order=mtime&type=0&tid=0&jsonp=jsonp`,
timeout: 1000 * settings.requestTimeout,
responseType: 'json',
onload: (res) => resolve(res),
onerror: (res) => reject(['请求失败', 'api.bilibili.com/medialist/gateway/base/spaceDetail', res.error]),
ontimeout: () => reject(['请求超时', 'api.bilibili.com/medialist/gateway/base/spaceDetail'])
});
});
if (response.response.code === -403 || response.response.code === 7201004) {
throw ['不支持处理私密收藏夹'];
} else if (response.response.code) {
throw ['发生未知错误, 请反馈该问题', JSON.stringify(response.response)];
}
if (!response.response.data.medias) {
addMessage('已完成');
return;
}
response.response.data.medias.forEach(media => {
const backup = GM_getValue(media.bvid, {
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,
biliplusExtra: null,
jijidown: null,
jijidownExtra: null,
xbeibeix: null,
});
formatBackup(backup, false, undefined);
let disabled = false;
if (media.title === '已失效视频') {
disabled = true;
}
if (!backup.BV) {
backup.BV = media.bvid;
}
if (!backup.AV) {
backup.AV = media.id;
}
if (!disabled) {
updateArrayDataInBackup(backup, 'title', media.title, getCurrentTs(), 'api.bilibili.com/medialist/gateway/base/spaceDetail');
updateArrayDataInBackup(backup, 'cover', media.cover, getCurrentTs(), 'api.bilibili.com/medialist/gateway/base/spaceDetail');
}
updateArrayDataInBackup(backup, 'intro', media.intro, getCurrentTs(), 'api.bilibili.com/medialist/gateway/base/spaceDetail');
if (!backup.upperUID) {
backup.upperUID = media.upper.mid;
}
updateArrayDataInBackup(backup, 'upperName', media.upper.name, getCurrentTs(), 'api.bilibili.com/medialist/gateway/base/spaceDetail');
updateArrayDataInBackup(backup, 'upperAvatar', media.upper.face, getCurrentTs(), 'api.bilibili.com/medialist/gateway/base/spaceDetail');
if (!backup.timeUpload) {
backup.timeUpload = media.ctime;
}
if (!backup.timePublish) {
backup.timePublish = media.pubtime;
}
updateTimeFavoriteInBackup(backup, media.fav_time, fid);
if (Array.isArray(media.pages)) {
media.pages.forEach(el => {
updatePagesInBackup(backup, el.page, el.title, undefined, undefined, el.id, getCurrentTs(), 'api.bilibili.com/medialist/gateway/base/spaceDetail');
});
} else {
if (enableDebug) {
addMessage('getFromApiLegacy 无法获取pages');
addMessage(media.bvid);
console.warn('getFromApiLegacy 无法获取pages');
console.warn(media);
}
}
const sortedBackup = {};
for (const sortedKey of sortedKeys) {
sortedBackup[sortedKey] = backup[sortedKey];
}
GM_setValue(media.bvid, sortedBackup);
if (enableDebug) console.log('保存旧版B站接口的数据至本地');
if (enableDebug) console.debug(media.bvid);
if (enableDebug) console.debug(sortedBackup);
});
count += response.response.data.medias.length;
addMessage(`已处理视频个数: ${count}`, true);
pageNumber++;
}
} catch (error) {
if (error instanceof Error) {
catchUnknownError(error);
} else {
addMessage(error[0], false, true);
for (let i = 1; i < error.length; i++) {
addMessage(error[i], true);
}
}
}
});
divButtonGetFromApiLegacy.appendChild(buttonGetFromApiLegacy);
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 = '重置timeFavorite';
button.addEventListener('click', () => {
try {
const backups = GM_getValues(GM_listValues());
delete backups.settings;
for (const BVOfBackup in backups) {
const backup = backups[BVOfBackup];
backup.timeFavorite = null;
GM_setValue(BVOfBackup, backup);
}
addMessage('已完成');
} catch (error) {
catchUnknownError(error);
}
});
divButton.appendChild(button);
}
di#####age = document.createElement('div');
di#####age.classList.add('backup-di#####age' + classAppendNewFreshSpace);
divControls.appendChild(di#####age);
// if (displayUpdate) {
//     setTimeout(() => {
//         addMessage(updates);
//     }, 300);
// }
if (!settings.processNormal && !settings.processDisabled) {
divLabelEnableGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetThumbnails.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL1.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL2.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL1.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL2.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
if (!settings.enableGetFromApi) {
divLabelEnableUpdateGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetThumbnails.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
if (!settings.enableUpdateGetFromApi) {
divLabelIntervalGetFromApi.classList.add('backup-disabled' + classAppendNewFreshSpace);
}
if (!settings.enableGetFromApiExtra) {
divLabelEnableGetThumbnails.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
if (!settings.enableUpdateGetFromApiExtra) {
divLabelIntervalGetFromApiExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
}
}
}
if (!settings.enableGetFromBiliplus) {
divLabelEnableUpdateGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
if (!settings.enableUpdateGetFromBiliplus) {
divLabelIntervalGetFromBiliplus.classList.add('backup-disabled' + classAppendNewFreshSpace);
}
}
if (!settings.enableGetFromApi || !settings.enableGetFromBiliplus) {
divLabelEnableGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
if (!settings.enableGetFromBiliplusExtra) {
divLabelEnableUpdateGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
if (!settings.enableUpdateGetFromBiliplusExtra) {
divLabelIntervalGetFromBiliplusExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
}
}
}
if (!settings.enableGetFromJijidown) {
divLabelEnableUpdateGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelEnableUpdateGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL1.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromJijidownURL2.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
if (!settings.enableUpdateGetFromJijidown) {
divLabelIntervalGetFromJijidown.classList.add('backup-disabled' + classAppendNewFreshSpace);
}
if (!settings.enableGetFromJijidownExtra) {
divLabelEnableUpdateGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
if (!settings.enableUpdateGetFromJijidownExtra) {
divLabelIntervalGetFromJijidownExtra.classList.add('backup-disabled' + classAppendNewFreshSpace);
}
}
}
if (!settings.enableGetFromXbeibeix) {
divLabelEnableUpdateGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divLabelIntervalGetFromXbeibeix.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL1.classList.add('backup-disabled' + classAppendNewFreshSpace);
divSwitchGetFromXbeibeixURL2.classList.add('backup-disabled' + classAppendNewFreshSpace);
} else {
if (!settings.enableUpdateGetFromXbeibeix) {
divLabelIntervalGetFromXbeibeix.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) {
if (dropdownContainer.childElementCount === 1) {
return;
}
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;
}
if (settings.appendDropdownCover || settings.appendDropdownLocal || settings.appendDropdownJump || settings.appendDropdownReset) {
dropdownContainer.lastElementChild.classList.add('be-dropdown-item-delimiter');
}
}
const backup = GM_getValue(BV, {});
if (settings.appendDropdownCover && 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(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(backup.cover[i].value, { insert: false, setParent: true });
}
} catch (error) {
catchUnknownError(error);
}
});
dropdownContainer.appendChild(dropdownCover);
}
if (settings.appendDropdownLocal) {
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);
}
if (settings.appendDropdownJump) {
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);
}
if (settings.appendDropdownReset) {
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 urlWithParams = await appendParamsForGetFromApi(fid, pageNumber, pageSize);
const response = await new Promise(async (resolve, reject) => {
GM.xmlHttpRequest({
method: 'GET',
url: urlWithParams,
timeout: 1000 * settings.requestTimeout,
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) addMessage('getFromApi 从B站接口获取的数据中没有该视频');
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.enableUpdateGetFromApiExtra && getCurrentTs() - backup.apiExtra.ts > 3600 * 24 * settings.intervalGetFromApiExtra))) {
} 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: 1000 * settings.requestTimeout,
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;
if (updateTimeFavoriteNeeded()) {
updateTimeFavoriteInBackup(backup, apiDetail.fav_time, fid);
}
if (apiDetail.ugc && apiDetail.ugc.first_cid) {
updatePagesInBackup(backup, 1, undefined, undefined, undefined, apiDetail.ugc.first_cid, getCurrentTs(), undefined);
}
if (newFreshSpace) {
spanFavTime.textContent = `投稿于:${formatTsTimePublish(1000 * apiDetail.pubtime)}`;
spanFavTime.setAttribute('title', new Date(1000 * apiDetail.pubtime).toLocaleString());
} else {
spanFavTime.textContent = `收藏于:${formatTsTimeFavorite(new Date(1000 * apiDetail.fav_time))}`;
spanFavTime.setAttribute('title', new Date(1000 * apiDetail.fav_time).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, controller) {
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: 1000 * settings.requestTimeout,
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'])
});
});
const currentTs = getCurrentTs();
updateArrayDataInBackup(backup, 'intro', response.response.data.desc, currentTs, '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) addMessage(`getFromApiExtra desc_v2未知type: ${desc.type}`);
if (enableDebug) console.warn(`getFromApiExtra desc_v2未知type: ${desc.type}`);
}
}
updateArrayDataInBackup(backup, 'intro', introWithUID, currentTs, '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, undefined, el.cid, getCurrentTs(), 'api.bilibili.com/x/web-interface/view');
});
if (settings.enableGetThumbnails && backup.AV && backup.pages) {
for (const page of backup.pages) {
if (controller.signal.aborted) {
throw new DOMException('', 'AbortError');
}
if (!page.cid) {
continue;
}
let getThumbnails = true;
if (page.thumbnails) {
for (const thumbnail of page.thumbnails) {
if (thumbnail.includes('videoshotpvhdboss')) {
getThumbnails = false;
break;
}
}
}
if (getThumbnails) {
const response = await new Promise((resolve, reject) => {
GM.xmlHttpRequest({
method: 'GET',
url: `https://api.bilibili.com/x/player/videoshot?aid=${backup.AV}&cid=${page.cid}`,
timeout: 1000 * settings.requestTimeout,
responseType: 'json',
onload: (res) => resolve(res),
onerror: (res) => reject(['请求失败', 'api.bilibili.com/x/player/videoshot', res.error]),
ontimeout: () => reject(['请求超时', 'api.bilibili.com/x/player/videoshot'])
});
});
if (!response.response.data.image || !response.response.data.image.length) {
if (enableDebug) {
addMessage('getFromApiExtra 无法获取thumbnails');
addMessage(response.response.message, true);
addMessage(`https://api.bilibili.com/x/player/videoshot?aid=${backup.AV}&cid=${page.cid}`, true);
console.warn('getFromApiExtra 无法获取thumbnails');
console.warn(response.response.message);
console.warn(`https://api.bilibili.com/x/player/videoshot?aid=${backup.AV}&cid=${page.cid}`);
}
continue;
}
response.response.data.image.forEach(el => {
updatePagesInBackup(backup, undefined, undefined, undefined, el, page.cid, undefined, undefined);
});
}
}
}
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: 1000 * settings.requestTimeout,
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, undefined, undefined, 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 (enableDebug) {
if (json.v2_app_api.cid && json.v2_app_api.cid !== json.list[0].cid) {
addMessage('getFromBiliplus cid 不一致1');
addMessage(json.v2_app_api.cid, true);
addMessage(json.list[0].cid, true);
console.warn('getFromBiliplus cid 不一致1');
console.warn(json.v2_app_api.cid);
console.warn(json.list[0].cid);
}
if (json.v2_app_api.cid && json.v2_app_api.cid !== json.v2_app_api.pages[0].cid) {
addMessage('getFromBiliplus cid 不一致2');
addMessage(json.v2_app_api.cid, true);
addMessage(json.v2_app_api.pages[0].cid, true);
console.warn('getFromBiliplus cid 不一致2');
console.warn(json.v2_app_api.cid);
console.warn(json.v2_app_api.pages[0].cid);
}
if (json.list[0].cid !== json.v2_app_api.pages[0].cid) {
addMessage('getFromBiliplus cid 不一致3');
addMessage(json.list[0].cid, true);
addMessage(json.v2_app_api.pages[0].cid, true);
console.warn('getFromBiliplus cid 不一致3');
console.warn(json.list[0].cid);
console.warn(json.v2_app_api.pages[0].cid);
}
}
if (json.v2_app_api.first_frame !== json.v2_app_api.pages[0].first_frame) {
if (enableDebug) {
addMessage('getFromBiliplus firstFrame 不一致');
addMessage(json.v2_app_api.first_frame, true);
addMessage(json.v2_app_api.pages[0].first_frame, true);
console.warn('getFromBiliplus firstFrame 不一致');
console.warn(json.v2_app_api.first_frame);
console.warn(json.v2_app_api.pages[0].first_frame);
}
updatePagesInBackup(backup, 0, undefined, json.v2_app_api.first_frame, undefined, 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, undefined, 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 getFromBiliplusExtra(AVBVTitle, backup, spanB) {
if (!backup.biliplus.value) {
backup.biliplusExtra = { value: false, ts: getCurrentTs() };
spanB.style.color = '#800000';
} else {
const response1 = await new Promise((resolve, reject) => {
GM.xmlHttpRequest({
method: 'GET',
url: `https://www.biliplus.com/all/video/av${AVBVTitle.AV}/`,
timeout: 1000 * settings.requestTimeout,
onload: (res) => resolve(res),
onerror: (res) => reject(['请求失败', 'www.biliplus.com/all/video', res.error]),
ontimeout: () => reject(['请求超时', 'www.biliplus.com/all/video'])
});
});
const paramsWithSign = response1.response.match(getParamsWithSignFromBiliplusRegex)[1];
const response2 = await new Promise((resolve, reject) => {
GM.xmlHttpRequest({
method: 'GET',
url: `https://www.biliplus.com/api/view_all${paramsWithSign}`,
timeout: 1000 * settings.requestTimeout,
responseType: 'json',
onload: (res) => resolve(res),
onerror: (res) => reject(['请求失败', 'www.biliplus.com/api/view_all', res.error]),
ontimeout: () => reject(['请求超时', 'www.biliplus.com/api/view_all'])
});
});
if (response2.response.code === -503) {
throw ['从BiliPlus获取额外数据的频率过快'];
}
await delay(2500);
if (response2.response.code === 0) {
if (enableDebug) console.log('从BiliPlus获取有效额外数据');
if (enableDebug) consoleAVBVTitle('debug', AVBVTitle);
if (enableDebug) console.debug(response2.response);
updateArrayDataInBackup(backup, 'title', response2.response.data.info.title, undefined, 'www.biliplus.com/api/view_all');
updateArrayDataInBackup(backup, 'intro', response2.response.data.info.description, undefined, 'www.biliplus.com/api/view_all');
updateArrayDataInBackup(backup, 'cover', response2.response.data.info.pic, undefined, 'www.biliplus.com/api/view_all');
updateArrayDataInBackup(backup, 'upperName', response2.response.data.info.author, undefined, 'www.biliplus.com/api/view_all');
response2.response.data.parts.forEach(el => {
updatePagesInBackup(backup, el.page, el.part, undefined, undefined, el.cid, undefined, 'www.biliplus.com/api/view_all');
});
backup.biliplusExtra = { value: true, ts: getCurrentTs() };
spanB.style.color = '#008000';
} else if (response2.response.code === -404) {
if (enableDebug) {
addMessage('getFromBiliplusExtra 无法获取额外数据');
addMessage(AVBVTitle.AV, true);
console.warn('getFromBiliplusExtra 无法获取额外数据');
console.warn(AVBVTitle.AV);
}
backup.biliplusExtra = { value: false, ts: getCurrentTs() };
spanB.style.color = '#800000';
} else {
if (enableDebug) {
addMessage('getFromBiliplusExtra 未知错误');
addMessage(JSON.stringify(response2.response), true);
addMessage(AVBVTitle.AV, true);
console.warn('getFromBiliplusExtra 未知错误');
console.warn(response2.response);
console.warn(AVBVTitle.AV);
}
backup.biliplusExtra = { value: false, ts: getCurrentTs() };
spanB.style.color = '#800000';
}
}
const sortedBackup = {};
for (const sortedKey of sortedKeys) {
sortedBackup[sortedKey] = backup[sortedKey];
}
GM_setValue(AVBVTitle.BV, sortedBackup);
if (enableDebug) console.log('保存BiliPlus的额外数据至本地');
if (enableDebug) consoleAVBVTitle('debug', AVBVTitle);
if (enableDebug) console.debug(sortedBackup);
}
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: 1000 * settings.requestTimeout,
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.enableUpdateGetFromJijidownExtra && getCurrentTs() - backup.jijidownExtra.ts > 3600 * 24 * 7 * settings.intervalGetFromJijidownExtra))) {
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.enableUpdateGetFromJijidownExtra && getCurrentTs() - backup.jijidownExtra.ts > 3600 * 24 * 7 * settings.intervalGetFromJijidownExtra))) {
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: 1000 * settings.requestTimeout,
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, 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: 1000 * settings.requestTimeout,
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';
}
di#####age.appendChild(p);
if (di#####ageHeightFixed) {
di#####age.scrollTop = di#####age.scrollHeight;
} else {
if (newFreshSpace) {
if (di#####age.scrollHeight > 320) {
di#####age.classList.add('backup-di#####age-heightFixed-newFreshSpace');
di#####ageHeightFixed = true;
di#####age.scrollTop = di#####age.scrollHeight;
}
} else {
if (di#####age.scrollHeight > 280) {
di#####age.classList.add('backup-di#####age-heightFixed');
di#####ageHeightFixed = true;
di#####age.scrollTop = di#####age.scrollHeight;
}
}
}
di#####age.scrollIntoView({ behavior: 'instant', block: 'nearest' });
}
function clearMessage() {
while (di#####age.firstChild) {
di#####age.removeChild(di#####age.firstChild);
}
di#####age.classList.remove('backup-di#####age-heightFixed' + classAppendNewFreshSpace);
di#####ageHeightFixed = 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(1000 * ts);
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) {
const n = new Date(e);
const 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 '昨天';
}
const l = n.getFullYear();
const c = '0'.concat(n.getMonth() + 1).slice(-2);
const 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 = 'https://' + 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, thumbnails, cid, ts, from) {
if (!index && index !== 0) {
index = null;
}
if (title) {
if (!Array.isArray(title)) {
title = [title];
}
} else {
title = null;
}
if (firstFrame) {
firstFrame = 'https://' + firstFrame.replace(getHttpsFromURLRegex, '').replace(getAvifFromURLRegex, '');
} else {
firstFrame = null;
}
if (thumbnails) {
if (!Array.isArray(thumbnails)) {
thumbnails = ['https://' + thumbnails.replace(getHttpsFromURLRegex, '').replace(getAvifFromURLRegex, '')];
} else {
thumbnails = thumbnails.map(el => 'https://' + el.replace(getHttpsFromURLRegex, '').replace(getAvifFromURLRegex, ''));
}
} else {
thumbnails = null;
}
if (!cid && cid !== 0) {
cid = null;
}
if (!ts) {
ts = 0;
}
if (!from) {
from = null;
}
if (!backup.pages) {
backup.pages = [];
const data = { index, title, firstFrame, thumbnails, 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 && target.ts <= ts) {
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)) {
target.title.push(el);
modified = true;
}
});
}
}
if (firstFrame) {
if (!target.firstFrame) {
target.firstFrame = firstFrame;
modified = true;
} else if (target.firstFrame !== firstFrame) {
if (enableDebug) {
addMessage('updatePagesInBackup firstFrame 不一致');
addMessage(`旧: ${target.firstFrame}`, true);
addMessage(`新: ${firstFrame}`, true);
console.warn('updatePagesInBackup firstFrame 不一致');
console.warn(`旧: ${target.firstFrame}`);
console.warn(`新: ${firstFrame}`);
}
// target.firstFrame = firstFrame;
// modified = true;
}
}
if (thumbnails) {
if (!target.thumbnails) {
target.thumbnails = thumbnails;
modified = true;
} else {
thumbnails.forEach(el => {
if (!target.thumbnails.find(ele => ele === el)) {
target.thumbnails.push(el);
modified = true;
}
});
}
}
if (target.ts <= ts) {
target.ts = ts;
modified = true;
}
if (modified) {
if (from) {
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 {
const data = { index, title, firstFrame, thumbnails, 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);
let divFilterOrder;
let divTid;
if (!newFreshSpace) {
const divDropdownFilterItems = document.querySelectorAll('div.fav-filters > div.be-dropdown.filter-item');
if (divDropdownFilterItems.length === 2) {
divFilterOrder = divDropdownFilterItems[1].querySelector('span');
divTid = divDropdownFilterItems[0].querySelector('span');
} else if (divDropdownFilterItems.length === 1) {
divFilterOrder = divDropdownFilterItems[0].querySelector('span');
divTid = null;
} else {
divFilterOrder = null;
divTid = null;
}
}
if (!newFreshSpace) {
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 (!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}`);
if (newFreshSpace) {
divTid = document.querySelector('div.fav-list-header-collapse div.radio-filter__item--active');
}
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: 1000 * settings.requestTimeout,
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 target = response.response.data.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) {
try {
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);
} catch (error) {
catchUnknownError(error);
}
}
function removeTsFromInBackup(obj) {
if (Array.isArray(obj)) {
obj.forEach(el => removeTsFromInBackup(el));
} else if (obj && typeof obj === 'object') {
for (const key in obj) {
if (key === 'ts' || key === 'from') {
delete obj[key];
} else {
removeTsFromInBackup(obj[key]);
}
}
}
}
function formatBackup(backup, setValue, BV) {
let modified = false;
// v9
if (backup.timeFavorite) {
backup.timeFavorite.forEach(el => {
if (typeof el.fid === 'string') {
el.fid = parseInt(el.fid, 10);
modified = true;
}
});
}
// v9
if (Array.isArray(backup.timeUpload)) {
if (backup.timeUpload.length === 1) {
backup.timeUpload = backup.timeUpload[0].value;
} else {
backup.timeUpload = null;
}
modified = true;
}
// v9
if (Array.isArray(backup.timePublish)) {
if (backup.timePublish.length === 1) {
backup.timePublish = backup.timePublish[0].value;
} else {
backup.timePublish = null;
}
modified = true;
}
// v10
if (backup.hasOwnProperty('jiji')) {
backup.jijidown = backup.jiji;
delete backup.jiji;
modified = true;
}
// v10
if (backup.hasOwnProperty('bbdownloader')) {
backup.xbeibeix = backup.bbdownloader;
delete backup.bbdownloader;
modified = true;
}
// v14
if (backup.hasOwnProperty('firstFrame')) {
delete backup.firstFrame;
modified = true;
}
// 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;
modified = true;
}
// v21
['cover', 'upperAvatar'].forEach(key => {
if (backup[key]) {
const tempBackup = {};
backup[key].forEach(el => {
updateArrayDataInBackup(tempBackup, key, el.value, el.ts, el.from);
});
backup[key] = tempBackup[key];
modified = true;
}
});
// v21
if (backup.pages) {
const tempBackup = {};
backup.pages.forEach(el => {
updatePagesInBackup(tempBackup, el.index, el.title, el.firstFrame, el.thumbnails, el.cid, el.ts, el.from);
});
backup.pages = tempBackup.pages;
modified = true;
}
if (setValue && modified) {
GM_setValue(BV, backup);
}
}
function updateTimeFavoriteNeeded() {
const divType = document.querySelector(newFreshSpace ? 'div.vui_input__prepend' : 'div.search-types');
let typeText = '当前';
if (divType) {
typeText = divType.innerText;
}
const inputKeyword = document.querySelector(newFreshSpace ? 'input.fav-list-header-filter__search' : 'input.search-fav-input');
if (!inputKeyword || !inputKeyword.value) {
typeText = '当前';
}
if (typeText.includes('当前')) {
console.warn(true);
return true;
} else if (typeText.includes('全部')) {
console.error(false);
return false;
} else {
throw ['无法确定搜索的范围为当前收藏夹还是全部收藏夹, 请反馈该问题'];
}
}
})();