您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
自动备份视频信息至本地和第三方网站, 失效视频信息回显
当前为
// ==UserScript== // @name bilibili favlist backup // @name:zh-CN 哔哩哔哩(B站|Bilibili)收藏夹Fix (备份视频信息) // @name:zh-TW 嗶哩嗶哩(B站|Bilibili)收藏夾Fix (備份影片資訊) // @namespace http://tampermonkey.net/ // @version 2 // @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 jijidown.com // @connect xbeibeix.com // @grant GM_openInTab // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_xmlhttpRequest // ==/UserScript== (function () { 'use strict'; const localizedText = { 'UPDATES': { 'zh-CN': '更新内容:<br>修复: 开启自动点击下一页后, 当前页的视频未处理完就切换至下一页的问题', 'zh-TW': '更新內容:<br>修復: 開啟自動點擊下一頁後, 當前頁的影片未處理完就切換至下一頁的問題' }, 'DROPDOWN_COVER': { 'zh-CN': '封面原图', 'zh-TW': '封面原圖' }, 'DROPDOWN_LOCAL': { 'zh-CN': '本地备份数据', 'zh-TW': '本地備份資料' }, 'DROPDOWN_JUMP': { 'zh-CN': '跳转至BJX', 'zh-TW': '跳轉至BJX' }, 'DROPDOWN_RESET': { 'zh-CN': '重置备份数据', 'zh-TW': '重置備份資料' }, 'ONLY_PROCESS_DISABLED': { 'zh-CN': '仅处理失效视频', 'zh-TW': '僅處理失效影片' }, 'AUTO_NEXT_PAGE': { 'zh-CN': '自动点击下一页', 'zh-TW': '自動點擊下一頁' }, 'ENABLE_DEBUG': { 'zh-CN': '控制台输出日志', 'zh-TW': '控制台輸出日誌' }, 'AV': { 'zh-CN': 'AV号', 'zh-TW': 'AV號' }, 'BV': { 'zh-CN': 'BV号', 'zh-TW': 'BV號' }, 'TITLE': { 'zh-CN': '标题', 'zh-TW': '標題' }, // 'POSITION_ON_THIS_PAGE': { // 'zh-CN': '在本页的位置', // 'zh-TW': '在本頁的位置' // }, // 'POSITION_ON_THIS_PAGE_WITH_PROMPT': { // 'zh-CN': '在本页的位置(从1开始)', // 'zh-TW': '在本頁的位置(從1開始)' // }, 'FID_NOT_FOUND_ERROR': { 'zh-CN': '无法获取当前收藏夹的fid, 刷新页面可能有帮助', 'zh-TW': '無法獲取當前收藏夾的fid, 重新載入頁面可能有幫助' }, 'REQUEST_TIMEOUT_ERROR': { 'zh-CN': '请求超时', 'zh-TW': '請求逾時' }, 'REQUEST_FAILED_ERROR': { 'zh-CN': '请求失败', 'zh-TW': '請求失敗' }, 'MULTIPLE_DROPDOWN_FOUND_ERROR': { 'zh-CN': '同时发现了多个下拉列表开关, 无法确定下拉列表所对应的视频, 刷新页面可能有帮助', 'zh-TW': '同時發現了多個下拉列表開關, 無法確定下拉列表所對應的影片, 重新載入頁面可能有幫助' }, 'TARGET_VIDEO_NOT_FOUND_ERROR': { 'zh-CN': '无法确定下拉列表所对应的视频, 请反馈该问题', 'zh-TW': '無法確定下拉列表所對應的影片, 請反饋該問題' }, 'UNKNOWN_ERROR': { 'zh-CN': '发生未知错误, 请反馈该问题', 'zh-TW': '發生未知錯誤, 請反饋該問題' }, }; const currentVersion = 2; const preferredLanguage = getPreferredLanguage(); const settings = GM_getValue('settings', { version: 0, onlyProcessDisabled: false, // alwaysGetIntroFromVideoPage: false, enableDebug: false, usageCount: 0, usageCountNewFreshSpace: 0, }); const favlistURLRegex = /https:\/\/space\.bilibili\.com\/\d+\/favlist.*/; const fidFromURLRegex = /fid=(\d+)/; const BVFromURLRegex = /video\/(\w{12})/; const httpsFromURLRegex = /^https?:\/\//; const jsonFromBiliplusRegex = /window\.addEventListener\('DOMContentLoaded',function\(\){view\((.+)\);}\);/; let AVBVs; let fidOfAVBVs; let onFavlistPage = false; let autoNextPage = false; let newFreshSpace; let videosPerPage; let displayPrompt; let processing; // let mutations_count = 0; // let mutation_count = 0; let firstTime = true; let divMessage; let activeControllers = new Set(); const favlistObserver = new MutationObserver((mutations, observer) => { if (settings.enableDebug) console.warn('callback favlistObserver'); if (document.querySelector('div.items')) { if (settings.enableDebug) console.warn('disconnect favlistObserver'); observer.disconnect(); newFreshSpace = true; videosPerPage = window.innerWidth < 1760 ? 40 : 36; addControls(); if (!firstTime) { main(); } if (settings.enableDebug) console.warn('observe itemsObserver'); itemsObserver.observe(document.querySelector('div.items'), { childList: true, attributes: false, characterData: false }); if (settings.enableDebug) console.warn('observe bodyChildListObserver'); bodyChildListObserver.observe(document.body, { childList: true, attributes: false, characterData: false }); return; } if (document.querySelector('div.fav-content.section')) { if (settings.enableDebug) console.warn('disconnect favlistObserver'); observer.disconnect(); newFreshSpace = false; videosPerPage = 20; addControls(); if (settings.enableDebug) console.warn('observe favContentSectionObserver'); favContentSectionObserver.observe(document.querySelector('div.fav-content.section'), { characterData: false, attributeFilter: ['class'] }); return; } }); const itemsObserver = new MutationObserver(async (mutations) => { stopAll(); if (settings.enableDebug) console.warn('callback itemsObserver'); await delay(100); // mainNewFreshSpace(); // mainNewFreshSpace(mutations); main(); }); const bodyChildListObserver = new MutationObserver(mutations => { if (settings.enableDebug) console.warn('callback bodyChildListObserver'); if (settings.enableDebug) console.log(mutations); for (const mutation of mutations) { for (const addedNode of mutation.addedNodes) { if (addedNode.nodeType === 1 && addedNode.classList.contains('bili-card-dropdown-popper')) { addDropdown(addedNode); // return; } if (addedNode.nodeType === 1 && addedNode.classList.contains('vui_toast--wrapper')) { stopAll(); if (settings.enableDebug) console.warn('disconncet itemsObserver'); itemsObserver.disconnect(); // return; } } for (const removedNode of mutation.removedNodes) { if (removedNode.nodeType === 1 && removedNode.classList.contains('vui_toast--wrapper')) { stopAll(); // mainNewFreshSpace(); main(); if (settings.enableDebug) console.warn('observe itemsObserver'); itemsObserver.observe(document.querySelector('div.items'), { childList: true, attributes: false, characterData: false }); // return; } } } }); const favContentSectionObserver = new MutationObserver(mutations => { if (settings.enableDebug) console.warn('callback favContentSectionObserver'); for (const mutation of mutations) { if (!mutation.target.classList.contains('loading')) { stopAll(); 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 (settings.enableDebug) console.warn('checkURL'); if (favlistURLRegex.test(location.href)) { if (!onFavlistPage) { onFavlistPage = true; if (settings.enableDebug) console.warn('observe favlistObserver'); favlistObserver.observe(document.body, { subtree: true, childList: true, attributes: false, characterData: false }); } } else { if (onFavlistPage) { stopAll(); onFavlistPage = false; if (settings.enableDebug) console.warn('disconnect favlistObserver'); favlistObserver.disconnect(); if (settings.enableDebug) console.warn('disconncet itemsObserver'); itemsObserver.disconnect(); if (settings.enableDebug) console.warn('disconncet bodyChildListObserver'); bodyChildListObserver.disconnect(); if (settings.enableDebug) console.warn('disconncet favContentSectionObserver'); favContentSectionObserver.disconnect(); } } } function getPreferredLanguage() { const languages = navigator.languages || [navigator.language]; for (const lang of languages) { if (lang === 'zh-CN') { return 'zh-CN'; } if (lang === 'zh-TW') { return 'zh-TW'; } if (lang === 'zh-HK') { return 'zh-TW'; } } return 'zh-CN'; } function getLocalizedText(key) { return localizedText[key][preferredLanguage]; } function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } function getCurrentTs() { return Math.floor(Date.now() / 1000); } function stopAll() { for (const controller of activeControllers) { controller.abort(); } } async function main() { if (settings.enableDebug) console.warn('============main============'); let controller; firstTime = false; try { processing = true; controller = new AbortController(); activeControllers.add(controller); let fid; if (newFreshSpace) { const fidFromURLMatch = location.href.match(fidFromURLRegex); if (fidFromURLMatch) { fid = fidFromURLMatch[1]; } else { // addMessage('-----------------------------'); addMessage(getLocalizedText('FID_NOT_FOUND_ERROR')); return; } } else { fid = document.querySelector('.fav-item.cur').getAttribute('fid'); } let pn; if (newFreshSpace) { const pagenation = document.querySelector('button.vui_pagenation--btn-num.vui_button--active'); if (!pagenation) { pn = 1; } else { pn = parseInt(pagenation.innerText, 10); } } else { pn = parseInt(document.querySelector('li.be-pager-item-active > a').innerText, 10); } let videos; if (newFreshSpace) { videos = document.querySelectorAll('div.items__item'); } else { videos = document.querySelectorAll('li.small-item'); } if (fid !== fidOfAVBVs || !AVBVs) { if (controller.signal.aborted) { // throw Error(); throw new DOMException('', 'AbortError'); } const response = await new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: 'GET', url: `https://api.bilibili.com/x/v3/fav/resource/ids?media_id=${fid}`, timeout: 5000, responseType: 'json', onload: (res) => resolve(res), onerror: () => reject(Error(getLocalizedText('REQUEST_FAILED_ERROR'))), ontimeout: () => reject(Error(getLocalizedText('REQUEST_TIMEOUT_ERROR'))) }); }); if (settings.enableDebug) console.warn(`update AVBVs, fid: ${fid}`); fidOfAVBVs = fid; AVBVs = response.response.data; } const _AVBVs = structuredClone(AVBVs); let apiDetails = {}; // for (const video of videos) { for (const [index, video] of videos.entries()) { let as; let AV; let BV; let title; try { if (controller.signal.aborted) { // throw Error(); throw new DOMException('', 'AbortError'); } let disabled = false; if (newFreshSpace && !video.querySelector('.bili-cover-card__stats')) { disabled = true; } else if (video.classList.contains('disabled')) { disabled = true; } if (settings.onlyProcessDisabled && !disabled) { continue; } as = video.querySelectorAll('a'); const divTitleNewFreshSpace = video.querySelector('.bili-video-card__title'); if (controller.signal.aborted) { // throw Error(); throw new DOMException('', 'AbortError'); } if (newFreshSpace) { BV = as[0].getAttribute('href').match(BVFromURLRegex)[1]; } else { BV = video.getAttribute('data-aid'); } AV = _AVBVs.find(_AVBV => _AVBV.bvid === BV).id; title = as[1].innerText; if (settings.enableDebug) console.warn('============video============'); if (settings.enableDebug) console.log(`index: ${index + 1}`); if (settings.enableDebug) consoleAVBVTitle('log', AV, BV, title); 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.innerText = `收藏于:`; 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'); // spanPubdate.innerText = metaText; // spanPubdate.innerText = metaText.replace(': ',': '); spanFavTime.innerText = metaText.replace(': ', ':'); spanFavTime.style.width = 'auto'; divMetaPubdate.appendChild(spanFavTime); // divTCABJX = document.createElement('div'); // divTCABJX.style.marginLeft = 'auto'; // // divTCABJX.style.display = 'block'; // divMetaPubdate.appendChild(divTCABJX); divTCABJX = divMetaPubdate; } const spanX = document.createElement('span'); spanX.innerText = 'X'; if (!newFreshSpace) { // spanX.style.marginRight = '11px'; spanX.style.marginRight = '9px'; } spanX.style.float = 'right'; spanX.style.fontWeight = 'bold'; spanX.style.cursor = 'pointer'; spanX.addEventListener('click', () => { try { GM_openInTab(`https://xbeibeix.com/video/${BV}`, { active: true, insert: false, setParent: true }); } catch (error) { catchUnknownError(error); } }); divTCABJX.appendChild(spanX); const spanJ = document.createElement('span'); spanJ.innerText = 'J'; spanJ.style.marginRight = '3px'; spanJ.style.float = 'right'; spanJ.style.fontWeight = 'bold'; spanJ.style.cursor = 'pointer'; spanJ.addEventListener('click', () => { try { GM_openInTab(`https://www.jijidown.com/video/${BV}`, { active: true, insert: false, setParent: true }); } catch (error) { catchUnknownError(error); } }); divTCABJX.appendChild(spanJ); const spanB = document.createElement('span'); spanB.innerText = 'B'; spanB.style.marginRight = '3px'; spanB.style.float = 'right'; spanB.style.fontWeight = 'bold'; spanB.style.cursor = 'pointer'; spanB.addEventListener('click', () => { try { GM_openInTab(`https://www.biliplus.com/video/${BV}`, { active: true, insert: false, setParent: true }); GM_openInTab(`https://www.biliplus.com/video/av${AV}`, { insert: false, setParent: true }); } catch (error) { catchUnknownError(error); } }); divTCABJX.appendChild(spanB); const spanA = document.createElement('span'); spanA.innerText = 'A'; spanA.style.marginRight = '3px'; spanA.style.float = 'right'; spanA.style.fontWeight = 'bold'; spanA.style.cursor = 'pointer'; spanA.addEventListener('click', () => { try { // GM_openInTab(`https://api.bilibili.com/x/v3/fav/resource/list?media_id=${fid}&pn=${pn}&ps=${videosPerPage}&keyword=&order=mtime&type=0&tid=0&platform=web`, { active: true, insert: false, setParent: true }); GM_openInTab(`https://api.bilibili.com/x/v3/fav/resource/list?media_id=${fid}&pn=${(pn - 1) * videosPerPage + index + 1}&ps=1&order=mtime`, { active: true, insert: false, setParent: true }); GM_openInTab(`https://api.bilibili.com/x/v3/fav/resource/infos?resources=${AV}%3A2&folder_id=${fid}`, { insert: false, setParent: true }); } catch (error) { catchUnknownError(error); } }); divTCABJX.appendChild(spanA); let backup = GM_getValue(BV, { AV: null, BV: null, title: null, intro: null, cover: null, upperUid: null, upperName: null, upperAvatar: null, timeUpload: null, timePublish: null, timeFavorite: null, firstFrame: null, api: null, biliplus: null, jijidown: null, xbeibeix: null, preferredTitle: null, preferredCover: null }); let functions = []; try { if (!backup.api || (backup.api.value === false && getCurrentTs() - backup.api.ts > 3600 * 1) || (backup.api.value === true && getCurrentTs() - backup.api.ts > 3600 * 1)) { await getFromApi(AV, BV, title, backup, spanA, apiDetails, fid, pn, disabled, spanFavTime); } else { spanA.style.color = backup.api.value ? '#00ff00' : '#ff0000'; if (backup.timeFavorite) { const target = backup.timeFavorite.find(i => i.fid === fid); if (target) { // spanFavTime.innerText = `收藏于: ${new Date(target.value * 1000).toLocaleString()}`; // spanFavTime.innerText = `收藏于: ${formatTimeFavorite1(target.value)}`; // spanFavTime.innerText = `收藏于: ${formatTimeFavorite2(new Date(target.value * 1000))}`; spanFavTime.innerText = `收藏于:${formatTimeFavorite2(new Date(target.value * 1000))}`; // spanFavTime.innerText = `收藏于: ${formatTimeFavorite3(target.value)}`; } } } if (!backup.jijidown || (backup.jijidown.value === false && getCurrentTs() - backup.jijidown.ts > 3600 * 24 * 30) || (backup.jijidown.value === true && getCurrentTs() - backup.jijidown.ts > 3600 * 24 * 30)) { functions.push(getFromJijidown(AV, BV, title, backup, spanJ)); } else { spanJ.style.color = backup.jijidown.value ? '#00ff00' : '#ff0000'; } if (!backup.xbeibeix || (backup.xbeibeix.value === false && getCurrentTs() - backup.xbeibeix.ts > 3600 * 24 * 30) || (backup.xbeibeix.value === true && getCurrentTs() - backup.xbeibeix.ts > 3600 * 24 * 30)) { functions.push(getFromXbeibeix(AV, BV, title, backup, spanX)); } else { spanX.style.color = backup.xbeibeix.value ? '#00ff00' : '#ff0000'; } if (!backup.biliplus || (backup.biliplus.value === false && getCurrentTs() - backup.biliplus.ts > 3600 * 24 * 30) || (backup.biliplus.value === true && getCurrentTs() - backup.biliplus.ts > 3600 * 24 * 30)) { functions.push(getFromBiliplus(AV, BV, title, backup, spanB)); } else { spanB.style.color = backup.biliplus.value ? '#00ff00' : '#ff0000'; } if (functions.length) { if (controller.signal.aborted) { // throw Error(); throw new DOMException('', 'AbortError'); } await Promise.all(functions); if (settings.enableDebug) console.warn('GM_setValue BJX'); if (settings.enableDebug) console.warn(`index: ${index + 1}`); if (settings.enableDebug) consoleAVBVTitle('warn', AV, BV, title); if (settings.enableDebug) console.warn(backup); GM_setValue(BV, backup); } } catch (error) { // if (controller.signal.aborted) { if (error.name === 'AbortError') { throw error; } else { // addMessage('-----------------------------'); addMessage(getLocalizedText('UNKNOWN_ERROR')); // addMessage(`fid: ${fid} pn: ${pn} index: ${index + 1}`, true); // addMessage(`${getLocalizedText('POSITION_ON_THIS_PAGE' + displayPrompt)}: ${index + 1}`, true); addMessageAVBVTitle(AV, BV, title); // addMessage(error.message, true); addMessage(error.stack, true); // console.error(`fid: ${fid} pn: ${pn} index: ${index + 1}`); console.error(`index: ${index + 1}`); consoleAVBVTitle('error', AV, BV, title); console.error(error); if (as[1]) { as[1].style.color = '#ff0000'; } } } // let mutiOther = 0; // if (backup.intro && backup.intro.length > 1) { // mutiOther = 1; // } // if (backup.timeUpload && backup.timeUpload.length > 1) { // mutiOther = 2; // } // if (backup.timePublish && backup.timePublish.length > 1) { // mutiOther = 2; // } let picture; let avifSource; let webpSource; let imgElement; if (newFreshSpace) { imgElement = video.querySelector('img'); } else { picture = video.querySelector('picture'); avifSource = picture.querySelector('source[type="image/avif"]'); webpSource = picture.querySelector('source[type="image/webp"]'); imgElement = picture.querySelector('img'); } if (disabled) { if (newFreshSpace) { if (backup.cover) { imgElement.setAttribute('src', `//${backup.cover[backup.cover.length - 1].value}@672w_378h_1c.avif`); } } else { video.classList.remove('disabled'); as[0].classList.remove('disabled'); // spanPubdate.style.textDecoration = 'line-through'; if (backup.cover) { avifSource.setAttribute('srcset', `//${backup.cover[backup.cover.length - 1].value}@320w_200h_1c_!web-space-favlist-video.avif`); webpSource.setAttribute('srcset', `//${backup.cover[backup.cover.length - 1].value}@320w_200h_1c_!web-space-favlist-video.webp`); imgElement.setAttribute('src', `//${backup.cover[backup.cover.length - 1].value}@320w_200h_1c_!web-space-favlist-video.webp`); } } as[1].style.textDecoration = 'line-through'; if (backup.title) { as[1].textContent = 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); } // } else { // as[1].textContent = '/////////////////////////////'; // as[1].textContent = ''; } } if (backup.cover && backup.cover.length > 1) { const spanC = document.createElement('span'); spanC.innerText = 'C'; spanC.style.marginRight = '3px'; spanC.style.float = 'right'; spanC.style.fontWeight = 'bold'; spanC.style.cursor = 'pointer'; spanC.style.color = '#000000'; let i = backup.cover.length - 2; spanC.addEventListener('click', () => { try { if (i < 0) { i = backup.cover.length - 1; } if (newFreshSpace) { imgElement.setAttribute('src', `//${backup.cover[i].value}@672w_378h_1c.avif`); } else { avifSource.setAttribute('srcset', `//${backup.cover[i].value}@320w_200h_1c_!web-space-favlist-video.avif`); webpSource.setAttribute('srcset', `//${backup.cover[i].value}@320w_200h_1c_!web-space-favlist-video.webp`); imgElement.setAttribute('src', `//${backup.cover[i].value}@320w_200h_1c_!web-space-favlist-video.webp`); } if (i !== backup.cover.length - 1) { spanC.style.color = '#999999'; } else { spanC.style.color = '#000000'; } i--; } catch (error) { catchUnknownError(error); } }); divTCABJX.appendChild(spanC); } if (backup.title && backup.title.length > 1) { const spanT = document.createElement('span'); spanT.innerText = 'T'; spanT.style.marginRight = '3px'; spanT.style.float = 'right'; spanT.style.fontWeight = 'bold'; spanT.style.cursor = 'pointer'; spanT.style.color = '#000000'; 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 (mutiOther) { // const spanO = document.createElement('span'); // spanO.innerText = 'O'; // spanO.style.marginRight = '3px'; // spanO.style.float = 'right'; // spanO.style.fontWeight = 'bold'; // spanO.style.cursor = 'pointer'; // spanO.style.color = mutiOther === 1 ? '#000000' : '#ff0000'; // spanO.addEventListener('click', () => { // try { // const data = GM_getValue(BV, {}); // // const json = JSON.stringify(data, null, 8); // 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); // } // }); // divTCABJX.appendChild(spanO); // } if (controller.signal.aborted) { // throw Error(); throw new DOMException('', 'AbortError'); } if (!newFreshSpace) { const ul = video.querySelector('ul.be-dropdown-menu'); addDropdown(ul, AV, BV); } if (functions.length === 1) { await delay(300); } } catch (error) { // if (controller.signal.aborted) { if (error.name === 'AbortError') { throw error; } else { // addMessage('-----------------------------'); addMessage(getLocalizedText('UNKNOWN_ERROR')); // addMessage(`fid: ${fid} pn: ${pn} index: ${index + 1}`, true); // addMessage(`${getLocalizedText('POSITION_ON_THIS_PAGE' + displayPrompt)}: ${index + 1}`, true); addMessageAVBVTitle(AV, BV, title); // addMessage(error.message, true); addMessage(error.stack, true); // console.error(`fid: ${fid} pn: ${pn} index: ${index + 1}`); console.error(`index: ${index + 1}`); consoleAVBVTitle('error', AV, BV, title); console.error(error); if (as[1]) { as[1].style.color = '#ff0000'; } } } } if (autoNextPage) { await clickNextPage(5000); } } catch (error) { // if (!controller.signal.aborted) { if (error.name !== 'AbortError') { catchUnknownError(error); } } finally { processing = false; activeControllers.delete(controller); } } function formatTimeFavorite1(t) { let e = Math.floor(+new Date / 1e3) - t; let n = (new Date).getFullYear(); let i = new Date(1e3 * t).getFullYear(); let r = new Date(1e3 * t).getMonth() + 1; let o = new Date(1e3 * t).getDate(); return e < 60 ? "刚刚" : e >= 60 && e < 3600 ? Math.floor(e / 60) + "分钟前" : e >= 3600 && e < 86400 ? Math.floor(e / 60 / 60) + "小时前" : 86400 === e ? "昨天" : e > 86400 && i === n ? r + "-" + o : i < n ? i + "-" + r + "-" + o : void 0; } function formatTimeFavorite2(t) { let e = new Date(); let n = e.getTime(); let r = t.getTime(); let 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 formatTimeFavorite3(t) { const date = new Date(t * 1000); const year = String(date.getFullYear()).slice(2); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); const hours = String(date.getHours()).padStart(2, '0'); const minutes = String(date.getMinutes()).padStart(2, '0'); const seconds = String(date.getSeconds()).padStart(2, '0'); return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; } // function decodeHTMLEntities(str) { // return str.replace(/&[a-zA-Z]+;/g, match => { // const textarea = document.createElement('textarea'); // textarea.innerHTML = match; // return textarea.value; // }); // } function decodeHTMLEntities(str) { return new DOMParser().parseFromString(`<!doctype html><body>${str}`, 'text/html').body.textContent; } function addMessage(msg, smallFontSize) { 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`; divMessage.appendChild(p); p.scrollIntoView({ behavior: 'instant', block: 'nearest' }); } function clearMessage() { while (divMessage.firstChild) { divMessage.removeChild(divMessage.firstChild); } } function addControls() { const newFreshSpaceAppend = newFreshSpace ? '-newFreshSpace' : ''; let displayUpdate = false; if (settings.version !== currentVersion) { if (settings.version) { displayUpdate = true; } settings.version = currentVersion; GM_setValue('settings', settings); } const usageCount = settings[newFreshSpace ? 'usageCountNewFreshSpace' : 'usageCount']; displayPrompt = usageCount < 10 ? '_WITH_PROMPT' : ''; if (displayPrompt) { settings[newFreshSpace ? 'usageCountNewFreshSpace' : 'usageCount']++; GM_setValue('settings', settings); } const style = document.createElement('style'); style.textContent = ` .fix-div { padding: 2px; } .fix-div-newFreshSpace { padding: 2px 0; } .fix-divControls { border-top: 1px solid #e4e9f0; } .fix-labelA, .fix-labelA-newFreshSpace { line-height: 1; } .fix-divMessage { line-height: 1.5; } `; 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('fix-div' + newFreshSpaceAppend); if (!newFreshSpace) { divControls.classList.add('fix-divControls'); } divSide.appendChild(divControls); const divLabelA = document.createElement('div'); divLabelA.classList.add('fix-div' + newFreshSpaceAppend); divControls.appendChild(divLabelA); const labelA = document.createElement('label'); labelA.classList.add('fix-labelA' + newFreshSpaceAppend); labelA.innerText = getLocalizedText('ONLY_PROCESS_DISABLED'); divLabelA.appendChild(labelA); const checkboxA = document.createElement('input'); checkboxA.type = 'checkbox'; checkboxA.checked = settings.onlyProcessDisabled; checkboxA.addEventListener('change', () => { try { settings.onlyProcessDisabled = checkboxA.checked; GM_setValue('settings', settings); } catch (error) { catchUnknownError(error); } }); labelA.insertAdjacentElement('afterbegin', checkboxA); const divLabelB = document.createElement('div'); divLabelB.classList.add('fix-div' + newFreshSpaceAppend); divControls.appendChild(divLabelB); const labelB = document.createElement('label'); labelB.classList.add('fix-labelA' + newFreshSpaceAppend); labelB.innerText = getLocalizedText('AUTO_NEXT_PAGE'); divLabelB.appendChild(labelB); const checkboxB = document.createElement('input'); checkboxB.type = 'checkbox'; checkboxB.checked = autoNextPage; checkboxB.addEventListener('change', () => { try { autoNextPage = checkboxB.checked; if (autoNextPage && !processing) { clickNextPage(500); } } catch (error) { catchUnknownError(error); } }); labelB.insertAdjacentElement('afterbegin', checkboxB); const divLabelC = document.createElement('div'); divLabelC.classList.add('fix-div' + newFreshSpaceAppend); divControls.appendChild(divLabelC); const labelC = document.createElement('label'); labelC.classList.add('fix-labelA' + newFreshSpaceAppend); labelC.innerText = getLocalizedText('ENABLE_DEBUG'); divLabelC.appendChild(labelC); const checkboxC = document.createElement('input'); checkboxC.type = 'checkbox'; checkboxC.checked = settings.enableDebug; checkboxC.addEventListener('change', () => { try { settings.enableDebug = checkboxC.checked; GM_setValue('settings', settings); } catch (error) { catchUnknownError(error); } }); labelC.insertAdjacentElement('afterbegin', checkboxC); divMessage = document.createElement('div'); divMessage.classList.add('fix-div' + newFreshSpaceAppend); divMessage.classList.add('fix-divMessage'); divControls.appendChild(divMessage); if (displayUpdate) { setTimeout(() => { addMessage(getLocalizedText('UPDATES')); }, 300); } } function addDropdown(dropdownContainer, AV, BV) { if (settings.enableDebug) console.warn('========addDropdown========'); try { if (newFreshSpace) { const biliCardDropdownVisible = document.querySelectorAll('.bili-card-dropdown--visible'); if (biliCardDropdownVisible.length !== 1) { // addMessage('-----------------------------'); addMessage(getLocalizedText('MULTIPLE_DROPDOWN_FOUND_ERROR')); return; } let divTargetVideo; try { divTargetVideo = document.querySelector('div.items__item:has(.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('-----------------------------'); addMessage(getLocalizedText('TARGET_VIDEO_NOT_FOUND_ERROR')); return; } if (settings.onlyProcessDisabled && divTargetVideo.querySelector('.bili-cover-card__stats')) { return; } BV = biliCardDropdownVisible[0].parentNode.querySelector('a').getAttribute('href').match(BVFromURLRegex)[1]; AV = AVBVs.find(AVBV => AVBV.bvid === BV).id; } else { if (dropdownContainer.lastElementChild.classList.contains('backup')) { return; } } if (!newFreshSpace) { dropdownContainer.lastElementChild.classList.add('be-dropdown-item-delimiter'); } const backup = GM_getValue(BV, {}); if (backup.cover) { const dropdownCover = document.createElement(newFreshSpace ? 'div' : 'li'); dropdownCover.classList.add(newFreshSpace ? 'bili-card-dropdown-popper__item' : 'be-dropdown-item'); if (!newFreshSpace) { dropdownCover.classList.add('backup'); } dropdownCover.textContent = getLocalizedText('DROPDOWN_COVER'); dropdownCover.addEventListener('click', () => { try { if (newFreshSpace) { dropdownContainer.classList.remove('visible'); } GM_openInTab(`https://${backup.cover[backup.cover.length - 1].value}`, { active: true, insert: true, setParent: true }); for (let i = backup.cover.length - 2; i >= 0; i--) { GM_openInTab(`https://${backup.cover[i].value}`, { insert: false, setParent: true }); } } catch (error) { catchUnknownError(error); } }); dropdownContainer.appendChild(dropdownCover); } const dropdownLocal = document.createElement('div'); dropdownLocal.classList.add(newFreshSpace ? 'bili-card-dropdown-popper__item' : 'be-dropdown-item'); if (!newFreshSpace) { dropdownLocal.classList.add('backup'); } dropdownLocal.textContent = getLocalizedText('DROPDOWN_LOCAL'); dropdownLocal.addEventListener('click', () => { try { if (newFreshSpace) { dropdownContainer.classList.remove('visible'); } const data = GM_getValue(BV, {}); // const json = JSON.stringify(data, null, 8); const json = JSON.stringify(data); // GM_openInTab('data:text/plain;charset=utf-8,' + encodeURIComponent(json), { active: true, insert: false, setParent: true }); GM_openInTab('data:application/json;charset=utf-8,' + encodeURIComponent(json), { active: true, insert: false, setParent: true }); } catch (error) { catchUnknownError(error); } }); dropdownContainer.appendChild(dropdownLocal); const dropdownJump = document.createElement('div'); dropdownJump.classList.add(newFreshSpace ? 'bili-card-dropdown-popper__item' : 'be-dropdown-item'); if (!newFreshSpace) { dropdownJump.classList.add('backup'); } dropdownJump.textContent = getLocalizedText('DROPDOWN_JUMP'); 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://www.biliplus.com/video/av${AV}`, { insert: false, setParent: true }); GM_openInTab(`https://www.jijidown.com/video/${BV}`, { insert: false, setParent: true }); GM_openInTab(`https://xbeibeix.com/video/${BV}`, { insert: false, setParent: true }); } catch (error) { catchUnknownError(error); } }); dropdownContainer.appendChild(dropdownJump); const dropdownReset = document.createElement('div'); dropdownReset.classList.add(newFreshSpace ? 'bili-card-dropdown-popper__item' : 'be-dropdown-item'); if (!newFreshSpace) { dropdownReset.classList.add('backup'); } dropdownReset.textContent = getLocalizedText('DROPDOWN_RESET'); 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 clickNextPage(ms) { if (newFreshSpace) { const pager = Array.from(document.querySelectorAll('button.vui_pagenation--btn-side')).find(b => b.innerText === '下一页'); if (pager && !pager.classList.contains('vui_button--disabled')) { await delay(ms); if (autoNextPage) { pager.click(); } } } else { const pager = document.querySelector('li.be-pager-next'); if (pager && !pager.classList.contains('be-pager-disabled')) { await delay(ms); if (autoNextPage) { pager.click(); } } } } function updateStoreArray(_backup, _key, _value, _ts = 0, _from) { if (!_backup[_key]) { _backup[_key] = []; const data = { value: _value, ts: _ts, from: _from }; if (settings.enableDebug) console.log(`init ${_key}`); if (settings.enableDebug) console.log(data); _backup[_key].push(data); } else { const target = _backup[_key].find(i => i.value === _value); if (target) { if (settings.enableDebug) console.log(`${_key} exists`); if (target.ts === 0 && _ts) { target.ts = _ts; target.from = _from; if (settings.enableDebug) console.warn(`overwrite ${_key} ts`); } } else { const data = { value: _value, ts: _ts, from: _from }; if (settings.enableDebug) console.log(`new ${_key}`); if (settings.enableDebug) console.log(data); _backup[_key].push(data); _backup[_key].sort((a, b) => a.ts - b.ts); } } } async function getFromApi(AV, BV, title, backup, spanA, apiDetails, fid, pn, disabled, spanFavTime) { if (!backup.AV) { backup.AV = AV; } if (!backup.BV) { backup.BV = BV; } if (!apiDetails.value) { const response = await new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: 'GET', url: `https://api.bilibili.com/x/v3/fav/resource/list?media_id=${fid}&pn=${pn}&ps=${videosPerPage}&keyword=&order=mtime&type=0&tid=0&platform=web`, timeout: 5000, responseType: 'json', onload: (res) => resolve(res), onerror: () => reject(Error(getLocalizedText('REQUEST_FAILED_ERROR'))), ontimeout: () => reject(Error(getLocalizedText('REQUEST_TIMEOUT_ERROR'))) }); }); apiDetails.value = response.response.data.medias; } const apiDetail = apiDetails.value.find(a => a.bvid === BV); if (!apiDetail) { throw Error('apiDetail not found in apidetails'); } if (disabled) { if (!backup.api || backup.api.value === false) { backup.api = { value: false, ts: getCurrentTs() }; spanA.style.color = '#ff0000'; } } else { backup.api = { value: true, ts: getCurrentTs() }; spanA.style.color = '#00ff00'; } if (settings.enableDebug) console.warn('getFromApi'); // if (settings.enableDebug) console.log(`index: ${index + 1}`); if (settings.enableDebug) consoleAVBVTitle('log', AV, BV, title); if (settings.enableDebug) console.log(apiDetail); if (!disabled) { updateStoreArray(backup, 'title', apiDetail.title, getCurrentTs(), 'api'); updateStoreArray(backup, 'cover', apiDetail.cover.replace(httpsFromURLRegex, ''), getCurrentTs(), 'api'); } // if (settings.alwaysGetIntroFromVideoPage) { // const response = await new Promise((resolve, reject) => { // GM.xmlHttpRequest({ // method: 'GET', // url: `https://www.bilibili.com/video/${BV}`, // timeout: 5000, // onload: (res) => resolve(res), // onerror: () => reject(Error(getLocalizedText('REQUEST_FAILED_ERROR'))), // ontimeout: () => reject(Error(getLocalizedText('REQUEST_TIMEOUT_ERROR'))) // }); // }); // if (settings.enableDebug) console.log(response); // // if (settings.enableDebug) console.warn('innerHTML'); // // if (settings.enableDebug) console.warn(response.responseXML.querySelector('div.basic-desc-info').innerHTML); // // if (settings.enableDebug) console.warn('innerText'); // // if (settings.enableDebug) console.warn(response.responseXML.querySelector('div.basic-desc-info').innerText); // // if (settings.enableDebug) console.warn('textContent'); // // if (settings.enableDebug) console.warn(response.responseXML.querySelector('div.basic-desc-info').textContent); // // if (settings.enableDebug) console.warn(decodeHTMLEntities(response.responseXML.querySelector('span.desc-info-text').innerHTML) === response.responseXML.querySelector('span.desc-info-text').innerText); // // if (settings.enableDebug) console.warn(response.responseXML.querySelector('span.desc-info-text').textContent === response.responseXML.querySelector('span.desc-info-text').innerText); // // if (settings.enableDebug) console.warn(response.responseXML.querySelector('span.desc-info-text').textContent === decodeHTMLEntities(response.responseXML.querySelector('span.desc-info-text').innerHTML)); // if (response.responseXML.querySelector('div.basic-desc-info')) { // updateStoreArray(backup, 'intro', response.responseXML.querySelector('div.basic-desc-info').innerText, getCurrentTs(), 'videoPage'); // if (!response.responseXML.querySelector('div.basic-desc-info').innerText.includes(apiDetail.intro)) { // // addMessage('-----------------------------'); // addMessage(getLocalizedText('UNKNOWN_ERROR')); // // addMessage(`${getLocalizedText('POSITION_ON_THIS_PAGE' + displayPrompt)}: ${index + 1}`, true); // addMessageAVBVTitle(AV, BV, title); // addMessage('intro from video page conflicts with apiDetail', true); // addMessage('getFromApi', true); // // console.error(`index: ${index + 1}`); // consoleAVBVTitle('error', AV, BV, title); // console.error('intro from video page conflicts with apiDetail'); // console.error('getFromApi'); // updateStoreArray(backup, 'intro', apiDetail.intro, getCurrentTs(), 'api'); // } // } else { // updateStoreArray(backup, 'intro', apiDetail.intro, getCurrentTs(), 'api'); // } // } else { if (!disabled && apiDetail.intro.length >= 250) { if (settings.enableDebug) console.log('apiDetail.intro.length >= 250'); const response = await new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: 'GET', url: `https://www.bilibili.com/video/${BV}`, timeout: 5000, onload: (res) => resolve(res), onerror: () => reject(Error(getLocalizedText('REQUEST_FAILED_ERROR'))), ontimeout: () => reject(Error(getLocalizedText('REQUEST_TIMEOUT_ERROR'))) }); }); if (settings.enableDebug) console.log(response); // if (settings.enableDebug) console.warn('innerHTML'); // if (settings.enableDebug) console.warn(response.responseXML.querySelector('div.basic-desc-info').innerHTML); // if (settings.enableDebug) console.warn('innerText'); // if (settings.enableDebug) console.warn(response.responseXML.querySelector('div.basic-desc-info').innerText); // if (settings.enableDebug) console.warn('textContent'); // if (settings.enableDebug) console.warn(response.responseXML.querySelector('div.basic-desc-info').textContent); // if (settings.enableDebug) console.warn(decodeHTMLEntities(response.responseXML.querySelector('span.desc-info-text').innerHTML) === response.responseXML.querySelector('span.desc-info-text').innerText); // if (settings.enableDebug) console.warn(response.responseXML.querySelector('span.desc-info-text').textContent === response.responseXML.querySelector('span.desc-info-text').innerText); // if (settings.enableDebug) console.warn(response.responseXML.querySelector('span.desc-info-text').textContent === decodeHTMLEntities(response.responseXML.querySelector('span.desc-info-text').innerHTML)); if (response.responseXML.querySelector('div.basic-desc-info')) { updateStoreArray(backup, 'intro', response.responseXML.querySelector('div.basic-desc-info').innerText, getCurrentTs(), 'videoPage'); if (!response.responseXML.querySelector('div.basic-desc-info').innerText.includes(apiDetail.intro)) { // // addMessage('-----------------------------'); // addMessage(getLocalizedText('UNKNOWN_ERROR')); // // addMessage(`${getLocalizedText('POSITION_ON_THIS_PAGE' + displayPrompt)}: ${index + 1}`, true); // addMessageAVBVTitle(AV, BV, title); // addMessage('intro from video page conflicts with apiDetail', true); // addMessage('getFromApi', true); // // console.error(`index: ${index + 1}`); // consoleAVBVTitle('error', AV, BV, title); // console.error('intro from video page conflicts with apiDetail'); // console.error('getFromApi'); updateStoreArray(backup, 'intro', apiDetail.intro, getCurrentTs(), 'api'); } } else { updateStoreArray(backup, 'intro', apiDetail.intro, getCurrentTs(), 'api'); } } else { updateStoreArray(backup, 'intro', apiDetail.intro, getCurrentTs(), 'api'); } // } if (!backup.upperUid) { backup.upperUid = apiDetail.upper.mid; } updateStoreArray(backup, 'upperName', apiDetail.upper.name, getCurrentTs(), 'api'); updateStoreArray(backup, 'upperAvatar', apiDetail.upper.face.replace(httpsFromURLRegex, ''), getCurrentTs(), 'api'); // if (!backup.timeUpload) { // backup.timeUpload = apiDetail.ctime; // } // if (!backup.timePublish) { // backup.timePublish = apiDetail.pubtime; // } updateStoreArray(backup, 'timeUpload', apiDetail.ctime, getCurrentTs(), 'api'); updateStoreArray(backup, 'timePublish', apiDetail.pubtime, getCurrentTs(), 'api'); if (!backup.timeFavorite) { backup.timeFavorite = []; const data = { value: apiDetail.fav_time, fid: fid }; if (settings.enableDebug) console.log('init timeFavorite'); if (settings.enableDebug) console.log(data); backup.timeFavorite.push(data); } else { const target = backup.timeFavorite.find(i => i.fid === fid); if (target) { if (target.value !== apiDetail.fav_time) { if (settings.enableDebug) console.warn('update timeFavorite'); target.value = apiDetail.fav_time; } } else { const data = { value: apiDetail.fav_time, fid: fid }; if (settings.enableDebug) console.log('new timeFavorite'); if (settings.enableDebug) console.log(data); backup.timeFavorite.push(data); backup.timeFavorite.sort((a, b) => a.value - b.value); } } spanFavTime.innerText = `收藏于:${formatTimeFavorite2(new Date(apiDetail.fav_time * 1000))}`; if (settings.enableDebug) console.warn('GM_setValue Api'); // if (settings.enableDebug) console.warn(`index: ${index + 1}`); if (settings.enableDebug) consoleAVBVTitle('warn', AV, BV, title); if (settings.enableDebug) console.warn(backup); GM_setValue(BV, backup); } async function getFromBiliplus(AV, BV, title, backup, spanB) { const response = await new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: 'GET', url: `https://www.biliplus.com/video/av${AV}`, timeout: 5000, onload: (res) => resolve(res), onerror: () => reject(Error(getLocalizedText('REQUEST_FAILED_ERROR'))), ontimeout: () => reject(Error(getLocalizedText('REQUEST_TIMEOUT_ERROR'))) }); }); const json = JSON.parse(response.response.match(jsonFromBiliplusRegex)[1]); if (json.title) { backup.biliplus = { value: true, ts: getCurrentTs() }; spanB.style.color = '#00ff00'; if (settings.enableDebug) console.warn('getFromBiliplus'); // if (settings.enableDebug) console.log(`index: ${index + 1}`); if (settings.enableDebug) consoleAVBVTitle('log', AV, BV, title); if (settings.enableDebug) console.log(json); updateStoreArray(backup, 'title', json.title, json.lastupdatets, 'biliplus'); updateStoreArray(backup, 'cover', json.pic.replace(httpsFromURLRegex, ''), json.lastupdatets, 'biliplus'); updateStoreArray(backup, 'intro', json.description, json.lastupdatets, 'biliplus'); updateStoreArray(backup, 'upperName', json.author, json.lastupdatets, 'biliplus'); updateStoreArray(backup, 'timePublish', json.created, json.lastupdatets, 'biliplus'); if (json.v2_app_api) { updateStoreArray(backup, 'title', json.v2_app_api.title, json.lastupdatets, 'biliplusV2'); updateStoreArray(backup, 'cover', json.v2_app_api.pic.replace(httpsFromURLRegex, ''), json.lastupdatets, 'biliplusV2'); updateStoreArray(backup, 'intro', json.v2_app_api.desc, json.lastupdatets, 'biliplusV2'); updateStoreArray(backup, 'upperName', json.v2_app_api.owner.name, json.lastupdatets, 'biliplusV2'); updateStoreArray(backup, 'upperAvatar', json.v2_app_api.owner.face.replace(httpsFromURLRegex, ''), json.lastupdatets, 'biliplusV2'); updateStoreArray(backup, 'timeUpload', json.v2_app_api.ctime, json.lastupdatets, 'biliplusV2'); updateStoreArray(backup, 'timePublish', json.v2_app_api.pubdate, json.lastupdatets, 'biliplusV2'); if (json.v2_app_api.first_frame) { updateStoreArray(backup, 'firstFrame', json.v2_app_api.first_frame.replace(httpsFromURLRegex, ''), json.lastupdatets, 'biliplusV2'); } } } else { backup.biliplus = { value: false, ts: getCurrentTs() }; spanB.style.color = '#ff0000'; if (settings.enableDebug) console.warn('getFromBiliplus'); // if (settings.enableDebug) console.warn(`index: ${index + 1}`); if (settings.enableDebug) consoleAVBVTitle('warn', AV, BV, title); if (settings.enableDebug) console.warn(json); } } async function getFromJijidown(AV, BV, title, backup, spanJ) { let retryCount = 0; while (true) { const response = await new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: 'GET', url: `https://www.jijidown.com/api/v1/video_bv/get_info?id=${BV.slice(2)}`, timeout: 5000, responseType: 'json', onload: (res) => resolve(res), onerror: () => reject(Error(getLocalizedText('REQUEST_FAILED_ERROR'))), ontimeout: () => reject(Error(getLocalizedText('REQUEST_TIMEOUT_ERROR'))) }); }); const json = response.response; if (json.upid > 0) { backup.jijidown = { value: true, ts: getCurrentTs() }; spanJ.style.color = '#00ff00'; if (settings.enableDebug) console.warn('getFromJijidown'); // if (settings.enableDebug) console.log(`index: ${index + 1}`); if (settings.enableDebug) consoleAVBVTitle('log', AV, BV, title); if (settings.enableDebug) console.log(json); updateStoreArray(backup, 'title', json.title, json.ltime, 'jijidown'); updateStoreArray(backup, 'cover', json.img.replace(httpsFromURLRegex, ''), json.ltime, 'jijidown'); updateStoreArray(backup, 'intro', decodeHTMLEntities(json.desc.replaceAll('<br/>', '\n')), json.ltime, 'jijidown'); if (json.up.id > 0) { updateStoreArray(backup, 'upperName', json.up.author, json.ltime, 'jijidown'); updateStoreArray(backup, 'upperAvatar', json.up.avatar.replace(httpsFromURLRegex, ''), json.ltime, 'jijidown'); } return; } else if (json.msg === 'loading') { retryCount++; if (settings.enableDebug) console.warn('getFromJijidown'); // if (settings.enableDebug) console.warn(`index: ${index + 1}`); if (settings.enableDebug) consoleAVBVTitle('warn', AV, BV, title); if (settings.enableDebug) console.warn(`retryCount: ${retryCount}`); if (settings.enableDebug) console.warn(json); if (retryCount > 4) { // addMessage('-----------------------------'); addMessageAVBVTitle(AV, BV, title); addMessage('retryCount > 4', true); addMessage('getFromJijidown', true); // console.error(`index: ${index + 1}`); consoleAVBVTitle('error', AV, BV, title); console.error('retryCount > 4'); console.error('getFromJijidown'); return; } } else { backup.jijidown = { value: false, ts: getCurrentTs() }; spanJ.style.color = '#ff0000'; if (settings.enableDebug) console.warn('getFromJijidown'); // if (settings.enableDebug) console.warn(`index: ${index + 1}`); if (settings.enableDebug) consoleAVBVTitle('warn', AV, BV, title); if (settings.enableDebug) console.warn(json); return; } await delay(600); } } async function getFromXbeibeix(AV, BV, title, backup, spanX) { const response = await new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: 'GET', url: `https://xbeibeix.com/video/${BV}`, timeout: 5000, onload: (res) => resolve(res), onerror: () => reject(Error(getLocalizedText('REQUEST_FAILED_ERROR'))), ontimeout: () => reject(Error(getLocalizedText('REQUEST_TIMEOUT_ERROR'))) }); }); if (response.finalUrl !== 'https://xbeibeix.com/') { backup.xbeibeix = { value: true, ts: getCurrentTs() }; spanX.style.color = '#00ff00'; if (settings.enableDebug) console.warn('getFromXbeibeix'); // if (settings.enableDebug) console.log(`index: ${index + 1}`); if (settings.enableDebug) consoleAVBVTitle('log', AV, BV, title); if (settings.enableDebug) console.log(response); updateStoreArray(backup, 'title', response.responseXML.querySelector('h5.fw-bold').innerText, undefined, 'xbeibeix'); updateStoreArray(backup, 'cover', response.responseXML.querySelector('div.col-4 > img').getAttribute('src').replace(httpsFromURLRegex, ''), undefined, 'xbeibeix'); updateStoreArray(backup, 'intro', decodeHTMLEntities(response.responseXML.querySelector('div.col-8 > textarea').innerText), undefined, 'xbeibeix'); updateStoreArray(backup, 'upperName', response.responseXML.querySelector('div.input-group.mb-2 > input').value, undefined, 'xbeibeix'); } else { backup.xbeibeix = { value: false, ts: getCurrentTs() }; spanX.style.color = '#ff0000'; if (settings.enableDebug) console.warn('getFromXbeibeix'); // if (settings.enableDebug) console.warn(`index: ${index + 1}`); if (settings.enableDebug) consoleAVBVTitle('warn', AV, BV, title); if (settings.enableDebug) console.warn(response); } } function consoleAVBVTitle(type, AV, BV, title) { switch (type) { case 'log': console.log(`AV: ${AV}`); console.log(`BV: ${BV}`); console.log(`title: ${title.slice(0, 13)}`); break; case 'warn': console.warn(`AV: ${AV}`); console.warn(`BV: ${BV}`); console.warn(`title: ${title.slice(0, 13)}`); break; case 'error': console.error(`AV: ${AV}`); console.error(`BV: ${BV}`); if (title) { console.error(`title: ${title.slice(0, 13)}`); } break; default: throw Error('invalid type'); } } function addMessageAVBVTitle(AV, BV, title) { addMessage(`${getLocalizedText('AV')}: ${AV}`, true); addMessage(`${getLocalizedText('BV')}: ${BV}`, true); if (title) { addMessage(`${getLocalizedText('TITLE')}: ${title.slice(0, 13)}`, true); } } function catchUnknownError(error) { // addMessage('-----------------------------'); addMessage(getLocalizedText('UNKNOWN_ERROR')); // addMessage(error.message, true); addMessage(error.stack, true); console.error(error); } // async function mainNewFreshSpace(mutations) { async function mainNewFreshSpace() { // mutations_count++; // console.error('mutations_count' + mutations_count); // for (const mutation of mutations) { // mutation_count++; // console.warn('mutation_count' + mutation_count); // console.log(mutation); // } // if (firstTime) { // firstTime = false; // } else { // mutations = mutations.reverse(); // } // for (const mutation of mutations) { // if (mutation.addedNodes.length) { // const items = document.querySelectorAll('.items__item'); // for (const item of items) { // console.log(mutation.addedNodes[0].querySelectorAll('a')); // console.log(mutation.addedNodes[0].querySelectorAll('a')[1].innerText); // mutation.addedNodes[0].querySelectorAll('a')[1].style.color = 'red'; // } } })();