您需要先安装一个扩展,例如 篡改猴、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 8 // @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_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': '重置備份資料' }, 'PROCESS_NORMAL': { 'zh-CN': '处理正常视频', 'zh-TW': '處理正常影片' }, 'PROCESS_DISABLED': { 'zh-CN': '处理失效视频', 'zh-TW': '處理失效影片' }, 'ENABLE_GET_FROM_API': { 'zh-CN': '从B站接口获取数据', 'zh-TW': '從B站介面獲取資料' }, 'ENABLE_GET_FROM_BILIPLUS': { 'zh-CN': '从BiliPlus获取数据', 'zh-TW': '從BiliPlus獲取資料' }, 'ENABLE_GET_FROM_JIJI': { 'zh-CN': '从唧唧获取数据 (尚不稳定)', 'zh-TW': '從唧唧獲取資料 (尚不穩定)' }, 'ENABLE_GET_FROM_BBDOWNLOADER': { 'zh-CN': '从贝贝工具站获取数据 (尚不稳定)', 'zh-TW': '從貝貝工具站獲取資料 (尚不穩定)' }, 'ENABLE_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': '標題' }, 'GET_AVBVS': { 'zh-CN': '获取当前收藏夹内所有视频的AV号, BV号', 'zh-TW': '獲取當前收藏夾內所有影片的AV號, BV號' }, 'GET_FROM_API': { 'zh-CN': '从B站接口获取数据', 'zh-TW': '從B站介面獲取資料' }, 'GET_FROM_BILIPLUS': { 'zh-CN': '从BiliPlus获取数据', 'zh-TW': '從BiliPlus獲取資料' }, 'GET_FROM_JIJI': { 'zh-CN': '从唧唧获取数据', 'zh-TW': '從唧唧獲取資料' }, 'GET_FROM_BBDOWNLOADER': { 'zh-CN': '从贝贝工具站获取数据', 'zh-TW': '從貝貝工具站獲取資料' }, 'FID_NOT_FOUND_ERROR': { 'zh-CN': '无法获取当前收藏夹的fid, 刷新页面可能有帮助', 'zh-TW': '無法獲取當前收藏夾的fid, 重新載入頁面可能有幫助' }, 'REQUEST_TIMEOUT_ERROR': { 'zh-CN': '请求超时', 'zh-TW': '請求逾時' }, 'REQUEST_FAILED_ERROR': { 'zh-CN': '请求失败', 'zh-TW': '請求失敗' }, 'REQUEST_MAXRETRIES_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 = 8; const preferredLanguage = getPreferredLanguage(); const favlistURLRegex = /https:\/\/space\.bilibili\.com\/\d+\/favlist.*/; const fidFromURLRegex = /fid=(\d+)/; const UIDFromURLRegex = /https:\/\/space\.bilibili\.com\/(\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 mutations_count = 0; // let mutation_count = 0; let firstTimeMain = true; let divMessage; let divMessageHeightFixed = false; // let lastTimeDivMessageScrollIntoViewTs = 0; const activeControllers = new Set(); const sortedKeys = [ 'BV', 'AV', 'title', 'intro', 'cover', 'upperUID', 'upperName', 'upperAvatar', 'timeUpload', 'timePublish', 'timeFavorite', 'firstFrame', 'api', 'biliplus', 'jiji', 'bbdownloader', 'preferredTitle', 'preferredCover', ]; const settings = GM_getValue('settings', { version: 0, processNormal: true, processDisabled: true, enableGetFromApi: true, enableGetFromBiliplus: true, enableGetFromJiji: false, enableGetFromBbdownloader: false, enableDebug: false, defaultFavlistFid: null, defaultUID: null, // alwaysGetIntroFromVideoPage: false, }); if (settings.hasOwnProperty('enableGetFromJijidown')) { settings.enableGetFromJiji = false; delete settings.enableGetFromJijidown; } if (settings.hasOwnProperty('enableGetFromXbeibeix')) { settings.enableGetFromBbdownloader = false; delete settings.enableGetFromXbeibeix; } const favlistObserver = new MutationObserver(async (_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 (!firstTimeMain) { await delay(200); 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) => { const itemsObserver = new MutationObserver(async () => { stopAll(); if (settings.enableDebug) console.warn('callback itemsObserver'); await delay(200); // 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(); } } } async function main() { if (settings.enableDebug) console.warn('============main============'); let controller; firstTimeMain = false; try { controller = new AbortController(); activeControllers.add(controller); let fid; if (newFreshSpace) { const fidFromURLMatch = location.href.match(fidFromURLRegex); if (fidFromURLMatch) { fid = parseInt(fidFromURLMatch[1], 10); if (!settings.defaultFavlistFid && !document.querySelector('div.vui_sidebar-item--active').parentNode.getAttribute('id')) { settings.defaultFavlistFid = fid; GM_setValue('settings', settings); } } else if (settings.defaultFavlistFid) { fid = settings.defaultFavlistFid; } else { addMessage(getLocalizedText('FID_NOT_FOUND_ERROR'), false, true); return; } } else { fid = parseInt(document.querySelector('.fav-item.cur').getAttribute('fid'), 10); } 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); } if (!settings.defaultUID) { settings.defaultUID = parseInt(location.href.match(UIDFromURLRegex)[1], 10); console.error(settings.defaultUID) GM_setValue('settings', settings); } 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: (res) => reject(Error(getLocalizedText('REQUEST_FAILED_ERROR') + res.error)), // ontimeout: () => reject(Error(getLocalizedText('REQUEST_TIMEOUT_ERROR'))) onerror: (res) => reject(['REQUEST_FAILED_ERROR', 'GET_AVBVS', res.error]), ontimeout: () => reject(['REQUEST_TIMEOUT_ERROR', 'GET_AVBVS']) }); }); if (settings.enableDebug) console.warn(`update AVBVs, fid: ${fid}`); fidOfAVBVs = fid; AVBVs = response.response.data; } const clonedAVBVs = structuredClone(AVBVs); const 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) { if (!video.querySelector('.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('.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 = clonedAVBVs.find(clonedAVBV => clonedAVBV.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'); // spanFavTime.innerText = metaText; // spanFavTime.innerText = metaText.replace(': ',': '); spanFavTime.innerText = metaText.replace(': ', ':'); spanFavTime.style.width = 'auto'; if (!newFreshSpace) { spanFavTime.style.lineHeight = '16px'; } divMetaPubdate.appendChild(spanFavTime); // divTCABJX = document.createElement('div'); // divTCABJX.style.marginLeft = 'auto'; // // divTCABJX.style.display = 'block'; // divMetaPubdate.appendChild(divTCABJX); divTCABJX = divMetaPubdate; } const spanX = document.createElement('span'); spanX.innerText = 'X'; if (!newFreshSpace) { // spanX.style.marginRight = '11px'; spanX.style.marginRight = '9px'; } spanX.style.float = 'right'; spanX.style.fontWeight = 'bold'; spanX.style.cursor = 'pointer'; if (!newFreshSpace) { spanX.style.lineHeight = '16px'; } spanX.addEventListener('click', () => { try { GM_openInTab(`https://bbdownloader.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'; if (!newFreshSpace) { spanJ.style.lineHeight = '16px'; } spanJ.addEventListener('click', () => { try { GM_openInTab(`https://www.jiji.moe/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'; if (!newFreshSpace) { spanB.style.lineHeight = '16px'; } 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'; if (!newFreshSpace) { spanA.style.lineHeight = '16px'; } 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); const backup = GM_getValue(BV, { BV: null, AV: 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, jiji: null, bbdownloader: null, // preferredTitle: null, // preferredCover: null }); if (backup.hasOwnProperty('jijidown')) { backup.jiji = backup.jijidown; delete backup.jijidown; } if (backup.hasOwnProperty('xbeibeix')) { backup.bbdownloader = backup.xbeibeix; delete backup.xbeibeix; } const functions = []; try { 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)}`; spanFavTime.setAttribute('title', new Date(target.value * 1000).toLocaleString()); // spanFavTime.setAttribute('title', formatTimeFavorite3(target.value)); } } if (settings.enableGetFromApi) { 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 (settings.enableGetFromJiji) { if (!backup.jiji || (backup.jiji.value === false && getCurrentTs() - backup.jiji.ts > 3600 * 24 * 30) || (backup.jiji.value === true && getCurrentTs() - backup.jiji.ts > 3600 * 24 * 30)) { functions.push(getFromJiji(AV, BV, title, backup, spanJ)); } else { spanJ.style.color = backup.jiji.value ? '#00ff00' : '#ff0000'; } } if (settings.enableGetFromBbdownloader) { if (!backup.bbdownloader || (backup.bbdownloader.value === false && getCurrentTs() - backup.bbdownloader.ts > 3600 * 24 * 30) || (backup.bbdownloader.value === true && getCurrentTs() - backup.bbdownloader.ts > 3600 * 24 * 30)) { functions.push(getFromBbdownloader(AV, BV, title, backup, spanX)); } else { spanX.style.color = backup.bbdownloader.value ? '#00ff00' : '#ff0000'; } } if (settings.enableGetFromBiliplus) { 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); const sortedBackup = {}; for (const sortedKey of sortedKeys) { sortedBackup[sortedKey] = backup[sortedKey]; } GM_setValue(BV, sortedBackup); if (settings.enableDebug) console.warn(sortedBackup); } } catch (error) { if (error instanceof Error) { // if (controller.signal.aborted) { if (error.name === 'AbortError') { throw error; } else { addMessage(getLocalizedText('UNKNOWN_ERROR'), false, true); // addMessage(`fid: ${fid} pn: ${pn} index: ${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'; } } } else { addMessage(getLocalizedText(error[0]), false, true); addMessageAVBVTitle(AV, BV, title); addMessage(getLocalizedText(error[1]), true); if (error[2]) { addMessage(error[2], true); } 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) { // video.style.opacity = '0.7'; if (newFreshSpace) { as[2].style.textDecoration = 'line-through'; as[2].style.opacity = '0.7'; 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'); 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`); } } 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; 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'; 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) { 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'; 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 (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'; // if (!newFreshSpace) { // spanO.style.lineHeight = '16px'; // } // 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(200); } } catch (error) { if (error instanceof Error) { // if (controller.signal.aborted) { if (error.name === 'AbortError') { throw error; } else { addMessage(getLocalizedText('UNKNOWN_ERROR'), false, true); // addMessage(`fid: ${fid} pn: ${pn} index: ${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'; } } } else { addMessage(getLocalizedText(error[0]), false, true); addMessageAVBVTitle(AV, BV, title); addMessage(getLocalizedText(error[1]), true); if (error[2]) { addMessage(error[2], true); } if (as[1]) { as[1].style.color = '#ff0000'; } } } } if (autoNextPage) { 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(5000); if (controller.signal.aborted) { // throw Error(); throw new DOMException('', 'AbortError'); } if (autoNextPage) { pager.click(); } } } else { const pager = document.querySelector('li.be-pager-next'); if (pager && !pager.classList.contains('be-pager-disabled')) { await delay(5000); if (controller.signal.aborted) { // throw Error(); throw new DOMException('', 'AbortError'); } if (autoNextPage) { pager.click(); } } } } } catch (error) { if (error instanceof Error) { // if (!controller.signal.aborted) { if (error.name !== 'AbortError') { catchUnknownError(error); } } else { addMessage(getLocalizedText(error[0]), false, true); addMessage(getLocalizedText(error[1]), true); if (error[2]) { addMessage(error[2], true); } } } finally { activeControllers.delete(controller); } } 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 style = document.createElement('style'); style.textContent = ` .fix-div { padding: 2px; } .fix-div-newFreshSpace { padding: 2px 0; } .fix-label { line-height: 1; } .fix-divMessage, .fix-divMessage-newFreshSpace { overflow-y: auto; background-color: #eeeeee; line-height: 1.5; scrollbar-width: none; } .fix-divMessage { margin: 2px; } .fix-divMessage::-webkit-scrollbar { display: none; } .fix-divMessage-newFreshSpace { margin: 2px 0; } .fix-divMessage-newFreshSpace::-webkit-scrollbar { display: none; } .fix-disabled { opacity: 0.5; pointer-events: 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('fix-div' + newFreshSpaceAppend); if (!newFreshSpace) { divControls.style.borderTop = '1px solid #e4e9f0'; } divSide.appendChild(divControls); let divLabelEnableGetFromApi; let divLabelEnableGetFromBiliplus; let divLabelEnableGetFromJiji; let divLabelEnableGetFromBbdownloader; const divLabelProcessNormal = document.createElement('div'); divLabelProcessNormal.classList.add('fix-div' + newFreshSpaceAppend); divControls.appendChild(divLabelProcessNormal); const labelProcessNormal = document.createElement('label'); labelProcessNormal.classList.add('fix-label'); labelProcessNormal.innerText = getLocalizedText('PROCESS_NORMAL'); divLabelProcessNormal.appendChild(labelProcessNormal); const checkboxProcessNormal = document.createElement('input'); checkboxProcessNormal.type = 'checkbox'; checkboxProcessNormal.checked = settings.processNormal; checkboxProcessNormal.addEventListener('change', () => { try { settings.processNormal = checkboxProcessNormal.checked; GM_setValue('settings', settings); if (!settings.processNormal && !settings.processDisabled) { divLabelEnableGetFromApi.classList.add('fix-disabled'); divLabelEnableGetFromBiliplus.classList.add('fix-disabled'); divLabelEnableGetFromJiji.classList.add('fix-disabled'); divLabelEnableGetFromBbdownloader.classList.add('fix-disabled'); } else { divLabelEnableGetFromApi.classList.remove('fix-disabled'); divLabelEnableGetFromBiliplus.classList.remove('fix-disabled'); divLabelEnableGetFromJiji.classList.remove('fix-disabled'); divLabelEnableGetFromBbdownloader.classList.remove('fix-disabled'); } } catch (error) { catchUnknownError(error); } }); labelProcessNormal.insertAdjacentElement('afterbegin', checkboxProcessNormal); const divLabelProcessDisabled = document.createElement('div'); divLabelProcessDisabled.classList.add('fix-div' + newFreshSpaceAppend); divControls.appendChild(divLabelProcessDisabled); const labelProcessDisabled = document.createElement('label'); labelProcessDisabled.classList.add('fix-label'); labelProcessDisabled.innerText = getLocalizedText('PROCESS_DISABLED'); divLabelProcessDisabled.appendChild(labelProcessDisabled); const checkboxProcessDisabled = document.createElement('input'); checkboxProcessDisabled.type = 'checkbox'; checkboxProcessDisabled.checked = settings.processDisabled; checkboxProcessDisabled.addEventListener('change', () => { try { settings.processDisabled = checkboxProcessDisabled.checked; GM_setValue('settings', settings); if (!settings.processNormal && !settings.processDisabled) { divLabelEnableGetFromApi.classList.add('fix-disabled'); divLabelEnableGetFromBiliplus.classList.add('fix-disabled'); divLabelEnableGetFromJiji.classList.add('fix-disabled'); divLabelEnableGetFromBbdownloader.classList.add('fix-disabled'); } else { divLabelEnableGetFromApi.classList.remove('fix-disabled'); divLabelEnableGetFromBiliplus.classList.remove('fix-disabled'); divLabelEnableGetFromJiji.classList.remove('fix-disabled'); divLabelEnableGetFromBbdownloader.classList.remove('fix-disabled'); } } catch (error) { catchUnknownError(error); } }); labelProcessDisabled.insertAdjacentElement('afterbegin', checkboxProcessDisabled); divLabelEnableGetFromApi = document.createElement('div'); divLabelEnableGetFromApi.classList.add('fix-div' + newFreshSpaceAppend); divControls.appendChild(divLabelEnableGetFromApi); const labelEnableGetFromApi = document.createElement('label'); labelEnableGetFromApi.classList.add('fix-label'); labelEnableGetFromApi.innerText = getLocalizedText('ENABLE_GET_FROM_API'); divLabelEnableGetFromApi.appendChild(labelEnableGetFromApi); const checkboxEnableGetFromApi = document.createElement('input'); checkboxEnableGetFromApi.type = 'checkbox'; checkboxEnableGetFromApi.checked = settings.enableGetFromApi; checkboxEnableGetFromApi.addEventListener('change', () => { try { settings.enableGetFromApi = checkboxEnableGetFromApi.checked; GM_setValue('settings', settings); } catch (error) { catchUnknownError(error); } }); labelEnableGetFromApi.insertAdjacentElement('afterbegin', checkboxEnableGetFromApi); divLabelEnableGetFromBiliplus = document.createElement('div'); divLabelEnableGetFromBiliplus.classList.add('fix-div' + newFreshSpaceAppend); divControls.appendChild(divLabelEnableGetFromBiliplus); const labelEnableGetFromBiliplus = document.createElement('label'); labelEnableGetFromBiliplus.classList.add('fix-label'); labelEnableGetFromBiliplus.innerText = getLocalizedText('ENABLE_GET_FROM_BILIPLUS'); divLabelEnableGetFromBiliplus.appendChild(labelEnableGetFromBiliplus); const checkboxEnableGetFromBiliplus = document.createElement('input'); checkboxEnableGetFromBiliplus.type = 'checkbox'; checkboxEnableGetFromBiliplus.checked = settings.enableGetFromBiliplus; checkboxEnableGetFromBiliplus.addEventListener('change', () => { try { settings.enableGetFromBiliplus = checkboxEnableGetFromBiliplus.checked; GM_setValue('settings', settings); } catch (error) { catchUnknownError(error); } }); labelEnableGetFromBiliplus.insertAdjacentElement('afterbegin', checkboxEnableGetFromBiliplus); divLabelEnableGetFromJiji = document.createElement('div'); divLabelEnableGetFromJiji.classList.add('fix-div' + newFreshSpaceAppend); divControls.appendChild(divLabelEnableGetFromJiji); const labelEnableGetFromJiji = document.createElement('label'); labelEnableGetFromJiji.classList.add('fix-label'); labelEnableGetFromJiji.innerText = getLocalizedText('ENABLE_GET_FROM_JIJI'); divLabelEnableGetFromJiji.appendChild(labelEnableGetFromJiji); const checkboxEnableGetFromJiji = document.createElement('input'); checkboxEnableGetFromJiji.type = 'checkbox'; checkboxEnableGetFromJiji.checked = settings.enableGetFromJiji; checkboxEnableGetFromJiji.addEventListener('change', () => { try { settings.enableGetFromJiji = checkboxEnableGetFromJiji.checked; GM_setValue('settings', settings); } catch (error) { catchUnknownError(error); } }); labelEnableGetFromJiji.insertAdjacentElement('afterbegin', checkboxEnableGetFromJiji); divLabelEnableGetFromBbdownloader = document.createElement('div'); divLabelEnableGetFromBbdownloader.classList.add('fix-div' + newFreshSpaceAppend); divControls.appendChild(divLabelEnableGetFromBbdownloader); const labelEnableGetFromBbdownloader = document.createElement('label'); labelEnableGetFromBbdownloader.classList.add('fix-label'); labelEnableGetFromBbdownloader.innerText = getLocalizedText('ENABLE_GET_FROM_BBDOWNLOADER'); divLabelEnableGetFromBbdownloader.appendChild(labelEnableGetFromBbdownloader); const checkboxEnableGetFromBbdownloader = document.createElement('input'); checkboxEnableGetFromBbdownloader.type = 'checkbox'; checkboxEnableGetFromBbdownloader.checked = settings.enableGetFromBbdownloader; checkboxEnableGetFromBbdownloader.addEventListener('change', () => { try { settings.enableGetFromBbdownloader = checkboxEnableGetFromBbdownloader.checked; GM_setValue('settings', settings); } catch (error) { catchUnknownError(error); } }); labelEnableGetFromBbdownloader.insertAdjacentElement('afterbegin', checkboxEnableGetFromBbdownloader); if (!settings.processNormal && !settings.processDisabled) { divLabelEnableGetFromApi.classList.add('fix-disabled'); divLabelEnableGetFromBiliplus.classList.add('fix-disabled'); divLabelEnableGetFromJiji.classList.add('fix-disabled'); divLabelEnableGetFromBbdownloader.classList.add('fix-disabled'); } else { divLabelEnableGetFromApi.classList.remove('fix-disabled'); divLabelEnableGetFromBiliplus.classList.remove('fix-disabled'); divLabelEnableGetFromJiji.classList.remove('fix-disabled'); divLabelEnableGetFromBbdownloader.classList.remove('fix-disabled'); } const divLabelAutoNextPage = document.createElement('div'); divLabelAutoNextPage.classList.add('fix-div' + newFreshSpaceAppend); divControls.appendChild(divLabelAutoNextPage); const labelAutoNextPage = document.createElement('label'); labelAutoNextPage.classList.add('fix-label'); labelAutoNextPage.innerText = getLocalizedText('ENABLE_AUTO_NEXT_PAGE'); divLabelAutoNextPage.appendChild(labelAutoNextPage); const checkboxAutoNextPage = document.createElement('input'); checkboxAutoNextPage.type = 'checkbox'; checkboxAutoNextPage.checked = autoNextPage; checkboxAutoNextPage.addEventListener('change', async () => { try { autoNextPage = checkboxAutoNextPage.checked; if (autoNextPage && !activeControllers.size) { 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(500); if (autoNextPage) { pager.click(); } } } else { const pager = document.querySelector('li.be-pager-next'); if (pager && !pager.classList.contains('be-pager-disabled')) { await delay(500); if (autoNextPage) { pager.click(); } } } } } catch (error) { catchUnknownError(error); } }); labelAutoNextPage.insertAdjacentElement('afterbegin', checkboxAutoNextPage); const divLabelEnableDebug = document.createElement('div'); divLabelEnableDebug.classList.add('fix-div' + newFreshSpaceAppend); divControls.appendChild(divLabelEnableDebug); const labelEnableDebug = document.createElement('label'); labelEnableDebug.classList.add('fix-label'); labelEnableDebug.innerText = getLocalizedText('ENABLE_DEBUG'); divLabelEnableDebug.appendChild(labelEnableDebug); const checkboxEnableDebug = document.createElement('input'); checkboxEnableDebug.type = 'checkbox'; checkboxEnableDebug.checked = settings.enableDebug; checkboxEnableDebug.addEventListener('change', () => { try { settings.enableDebug = checkboxEnableDebug.checked; GM_setValue('settings', settings); } catch (error) { catchUnknownError(error); } }); labelEnableDebug.insertAdjacentElement('afterbegin', checkboxEnableDebug); divMessage = document.createElement('div'); divMessage.classList.add('fix-divMessage' + newFreshSpaceAppend); divControls.appendChild(divMessage); if (displayUpdate) { setTimeout(() => { addMessage(getLocalizedText('UPDATES')); }, 300); } } function addDropdown(dropdownContainer, AV, BV) { try { if (newFreshSpace) { const biliCardDropdownVisible = document.querySelectorAll('.bili-card-dropdown--visible'); if (biliCardDropdownVisible.length !== 1) { addMessage(getLocalizedText('MULTIPLE_DROPDOWN_FOUND_ERROR'), false, true); 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(getLocalizedText('TARGET_VIDEO_NOT_FOUND_ERROR'), false, true); return; } if (!settings.processNormal && divTargetVideo.querySelector('.bili-cover-card__stats')) { return; } if (!settings.processDisabled && !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.jiji.moe/video/${BV}`, { insert: false, setParent: true }); GM_openInTab(`https://bbdownloader.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 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: (res) => reject(Error(getLocalizedText('REQUEST_FAILED_ERROR') + res.error)), // ontimeout: () => reject(Error(getLocalizedText('REQUEST_TIMEOUT_ERROR'))) onerror: (res) => reject(['REQUEST_FAILED_ERROR', 'GET_FROM_API', res.error]), ontimeout: () => reject(['REQUEST_TIMEOUT_ERROR', 'GET_FROM_API']) }); }); 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.bilibili.com/x/v3/fav/resource/list'); updateStoreArray(backup, 'cover', apiDetail.cover.replace(httpsFromURLRegex, ''), getCurrentTs(), 'api.bilibili.com/x/v3/fav/resource/list'); } // 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: (res) => reject(Error(getLocalizedText('REQUEST_FAILED_ERROR') + res.error)), // // ontimeout: () => reject(Error(getLocalizedText('REQUEST_TIMEOUT_ERROR'))) // onerror: (res) => reject(['REQUEST_FAILED_ERROR', 'GET_FROM_API', res.error]), // ontimeout: () => reject(['REQUEST_TIMEOUT_ERROR', 'GET_FROM_API']) // }); // }); // 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(), 'www.bilibili.com/video'); // if (!response.responseXML.querySelector('div.basic-desc-info').innerText.includes(apiDetail.intro)) { // addMessage(getLocalizedText('UNKNOWN_ERROR'), false, 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.bilibili.com/x/v3/fav/resource/list'); // } // } else { // updateStoreArray(backup, 'intro', apiDetail.intro, getCurrentTs(), 'api.bilibili.com/x/v3/fav/resource/list'); // } // } 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: (res) => reject(Error(getLocalizedText('REQUEST_FAILED_ERROR') + res.error)), // ontimeout: () => reject(Error(getLocalizedText('REQUEST_TIMEOUT_ERROR'))) onerror: (res) => reject(['REQUEST_FAILED_ERROR', 'GET_FROM_API', res.error]), ontimeout: () => reject(['REQUEST_TIMEOUT_ERROR', 'GET_FROM_API']) }); }); 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(), 'www.bilibili.com/video'); if (!response.responseXML.querySelector('div.basic-desc-info').innerText.includes(apiDetail.intro)) { // addMessage(getLocalizedText('UNKNOWN_ERROR'), false, 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.bilibili.com/x/v3/fav/resource/list'); } } else { updateStoreArray(backup, 'intro', apiDetail.intro, getCurrentTs(), 'api.bilibili.com/x/v3/fav/resource/list'); } } else { updateStoreArray(backup, 'intro', apiDetail.intro, getCurrentTs(), 'api.bilibili.com/x/v3/fav/resource/list'); } // } if (!backup.upperUID) { backup.upperUID = apiDetail.upper.mid; } updateStoreArray(backup, 'upperName', apiDetail.upper.name, getCurrentTs(), 'api.bilibili.com/x/v3/fav/resource/list'); updateStoreArray(backup, 'upperAvatar', apiDetail.upper.face.replace(httpsFromURLRegex, ''), getCurrentTs(), 'api.bilibili.com/x/v3/fav/resource/list'); // if (!backup.timeUpload) { // backup.timeUpload = apiDetail.ctime; // } // if (!backup.timePublish) { // backup.timePublish = apiDetail.pubtime; // } updateStoreArray(backup, 'timeUpload', apiDetail.ctime, getCurrentTs(), 'api.bilibili.com/x/v3/fav/resource/list'); updateStoreArray(backup, 'timePublish', apiDetail.pubtime, getCurrentTs(), 'api.bilibili.com/x/v3/fav/resource/list'); 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.log('update timeFavorite'); target.value = apiDetail.fav_time; backup.timeFavorite.sort((a, b) => a.value - b.value); } } 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))}`; // spanFavTime.setAttribute('title', formatTimeFavorite3(apiDetail.fav_time)); spanFavTime.setAttribute('title', new Date(apiDetail.fav_time * 1000).toLocaleString()); if (settings.enableDebug) console.warn('GM_setValue Api'); // if (settings.enableDebug) console.warn(`index: ${index + 1}`); if (settings.enableDebug) consoleAVBVTitle('warn', AV, BV, title); const sortedBackup = {}; for (const sortedKey of sortedKeys) { sortedBackup[sortedKey] = backup[sortedKey]; } GM_setValue(BV, sortedBackup); if (settings.enableDebug) console.warn(sortedBackup); } 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: (res) => reject(Error(getLocalizedText('REQUEST_FAILED_ERROR') + res.error)), // ontimeout: () => reject(Error(getLocalizedText('REQUEST_TIMEOUT_ERROR'))) onerror: (res) => reject(['REQUEST_FAILED_ERROR', 'GET_FROM_BILIPLUS', res.error]), ontimeout: () => reject(['REQUEST_TIMEOUT_ERROR', 'GET_FROM_BILIPLUS']) }); }); 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, 'www.biliplus.com/video'); updateStoreArray(backup, 'cover', json.pic.replace(httpsFromURLRegex, ''), json.lastupdatets, 'www.biliplus.com/video'); updateStoreArray(backup, 'intro', json.description, json.lastupdatets, 'www.biliplus.com/video'); updateStoreArray(backup, 'upperName', json.author, json.lastupdatets, 'www.biliplus.com/video'); updateStoreArray(backup, 'timePublish', json.created, json.lastupdatets, 'www.biliplus.com/video'); if (json.v2_app_api) { updateStoreArray(backup, 'title', json.v2_app_api.title, json.lastupdatets, 'www.biliplus.com/video'); updateStoreArray(backup, 'cover', json.v2_app_api.pic.replace(httpsFromURLRegex, ''), json.lastupdatets, 'www.biliplus.com/video'); updateStoreArray(backup, 'intro', json.v2_app_api.desc, json.lastupdatets, 'www.biliplus.com/video'); updateStoreArray(backup, 'upperName', json.v2_app_api.owner.name, json.lastupdatets, 'www.biliplus.com/video'); updateStoreArray(backup, 'upperAvatar', json.v2_app_api.owner.face.replace(httpsFromURLRegex, ''), json.lastupdatets, 'www.biliplus.com/video'); updateStoreArray(backup, 'timeUpload', json.v2_app_api.ctime, json.lastupdatets, 'www.biliplus.com/video'); updateStoreArray(backup, 'timePublish', json.v2_app_api.pubdate, json.lastupdatets, 'www.biliplus.com/video'); if (json.v2_app_api.first_frame) { updateStoreArray(backup, 'firstFrame', json.v2_app_api.first_frame.replace(httpsFromURLRegex, ''), json.lastupdatets, 'www.biliplus.com/video'); } } } 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 getFromJiji(AV, BV, title, backup, spanJ) { let retryCount = 0; while (true) { const response = await new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: 'GET', url: `https://www.jiji.moe/api/v1/video_bv/get_info?id=${BV.slice(2)}`, timeout: 5000, responseType: 'json', onload: (res) => resolve(res), // onerror: (res) => reject(Error(getLocalizedText('REQUEST_FAILED_ERROR') + res.error)), // ontimeout: () => reject(Error(getLocalizedText('REQUEST_TIMEOUT_ERROR'))) onerror: (res) => reject(['REQUEST_FAILED_ERROR', 'GET_FROM_JIJI', res.error]), ontimeout: () => reject(['REQUEST_TIMEOUT_ERROR', 'GET_FROM_JIJI']) }); }); if (settings.enableDebug) console.log(response); if (response.status !== 200) { throw ['REQUEST_FAILED_ERROR', 'GET_FROM_JIJI', `${response.status} ${response.statusText}`]; } const json = response.response; if (json.upid > 0) { backup.jiji = { value: true, ts: getCurrentTs() }; spanJ.style.color = '#00ff00'; if (settings.enableDebug) console.warn('getFromJiji'); // 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, 'www.jiji.moe/api/v1/video_bv/get_info'); updateStoreArray(backup, 'cover', json.img.replace(httpsFromURLRegex, ''), json.ltime, 'www.jiji.moe/api/v1/video_bv/get_info'); updateStoreArray(backup, 'intro', decodeHTMLEntities(json.desc.replaceAll('<br/>', '\n')), json.ltime, 'www.jiji.moe/api/v1/video_bv/get_info'); if (json.up.id > 0) { updateStoreArray(backup, 'upperName', json.up.author, json.ltime, 'www.jiji.moe/api/v1/video_bv/get_info'); updateStoreArray(backup, 'upperAvatar', json.up.avatar.replace(httpsFromURLRegex, ''), json.ltime, 'www.jiji.moe/api/v1/video_bv/get_info'); } return; } else if (json.msg === 'loading') { retryCount++; if (settings.enableDebug) console.warn('getFromJiji'); // 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) { throw ['REQUEST_MAXRETRIES_ERROR', 'GET_FROM_JIJI']; } } else { backup.jiji = { value: false, ts: getCurrentTs() }; spanJ.style.color = '#ff0000'; if (settings.enableDebug) console.warn('getFromJiji'); // 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 getFromBbdownloader(AV, BV, title, backup, spanX) { const response = await new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: 'GET', url: `https://bbdownloader.com/video/${BV}`, timeout: 5000, onload: (res) => resolve(res), // onerror: (res) => reject(Error(getLocalizedText('REQUEST_FAILED_ERROR') + res.error)), // ontimeout: () => reject(Error(getLocalizedText('REQUEST_TIMEOUT_ERROR'))) onerror: (res) => reject(['REQUEST_FAILED_ERROR', 'GET_FROM_BBDOWNLOADER', res.error]), ontimeout: () => reject(['REQUEST_TIMEOUT_ERROR', 'GET_FROM_BBDOWNLOADER']) }); }); if (response.finalUrl !== 'https://bbdownloader.com/') { backup.bbdownloader = { value: true, ts: getCurrentTs() }; spanX.style.color = '#00ff00'; if (settings.enableDebug) console.warn('getFromBbdownloader'); // 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, 'bbdownloader.com/video'); updateStoreArray(backup, 'cover', response.responseXML.querySelector('div.col-4 > img').getAttribute('src').replace(httpsFromURLRegex, ''), undefined, 'bbdownloader.com/video'); updateStoreArray(backup, 'intro', decodeHTMLEntities(response.responseXML.querySelector('div.col-8 > textarea').innerText), undefined, 'bbdownloader.com/video'); updateStoreArray(backup, 'upperName', response.responseXML.querySelector('div.input-group.mb-2 > input').value, undefined, 'bbdownloader.com/video'); } else { backup.bbdownloader = { value: false, ts: getCurrentTs() }; spanX.style.color = '#ff0000'; if (settings.enableDebug) console.warn('getFromBbdownloader'); // if (settings.enableDebug) console.warn(`index: ${index + 1}`); if (settings.enableDebug) consoleAVBVTitle('warn', AV, BV, title); if (settings.enableDebug) console.warn(response); } } 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 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 addMessage(msg, smallFontSize, border) { let px; if (smallFontSize) { px = newFreshSpace ? 11 : 10; } else { px = newFreshSpace ? 13 : 12; } const p = document.createElement('p'); p.innerHTML = msg; p.style.fontSize = `${px}px`; if (border) { p.style.borderTop = '1px solid #ff0000'; } divMessage.appendChild(p); if (divMessageHeightFixed) { divMessage.scrollTop = divMessage.scrollHeight; } else { if (newFreshSpace) { if (divMessage.scrollHeight > 300) { divMessage.style.height = '300px'; divMessageHeightFixed = true; divMessage.scrollTop = divMessage.scrollHeight; } } else { if (divMessage.scrollHeight > 250) { divMessage.style.height = '250px'; divMessageHeightFixed = true; divMessage.scrollTop = divMessage.scrollHeight; } } } // if (getCurrentTs() - lastTimeDivMessageScrollIntoViewTs > 5) { divMessage.scrollIntoView({ behavior: 'instant', block: 'nearest' }); // lastTimeDivMessageScrollIntoViewTs = getCurrentTs(); // } } // function clearMessage() { // while (divMessage.firstChild) { // divMessage.removeChild(divMessage.firstChild); // } // } 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 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 catchUnknownError(error) { addMessage(getLocalizedText('UNKNOWN_ERROR'), false, true); // addMessage(error.message, 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 stopAll() { for (const controller of activeControllers) { controller.abort(); } } // function formatTimeFavorite1(t) { // const e = Math.floor(+new Date / 1e3) - t; // const n = (new Date).getFullYear(); // const i = new Date(1e3 * t).getFullYear(); // const r = new Date(1e3 * t).getMonth() + 1; // const 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) { 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 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 updateStoreArray(backup, key, value, ts = 0, from) { if (!backup[key]) { backup[key] = []; const data = { value, ts, 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 < ts) { target.ts = ts; target.from = from; backup[key].sort((a, b) => a.ts - b.ts); if (settings.enableDebug) console.warn(`overwrite ${key} ts`); } } else { const data = { value, ts, 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 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'; // } // } })();