您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
手动备份视频信息至biliplus, xbeibeix, jijidown, 以便失效后查看
当前为
// ==UserScript== // @name 哔哩哔哩(B站|Bilibili)收藏夹Fix(多网站跳转) // @name:zh-CN 哔哩哔哩(B站|Bilibili)收藏夹Fix(多网站跳转) // @name:zh-TW 嗶哩嗶哩(B站|Bilibili)收藏夾Fix(多網站跳轉) // @namespace http://tampermonkey.net/ // @version 1.2.3 // @description 手动备份视频信息至biliplus, xbeibeix, jijidown, 以便失效后查看 // @description:zh-CN 手动备份视频信息至biliplus, xbeibeix, jijidown, 以便失效后查看 // @description:zh-TW 手動備份影片資訊至biliplus, xbeibeix, jijidown, 以便失效後查看 // @author YTB0710 // @match https://space.bilibili.com/* // @connect bilibili.com // @grant GM_openInTab // @grant GM_xmlhttpRequest // ==/UserScript== (function () { 'use strict'; const localizedText = { 'DROPDOWN_JUMP': { 'zh-CN': '跳转至BXJ', 'zh-TW': '跳轉至BXJ' }, 'DROPDOWN_COVER': { 'zh-CN': '封面原图', 'zh-TW': '封面原圖' }, 'DROPDOWN_SPACE': { 'zh-CN': 'UP主空间', 'zh-TW': 'UP主主頁' }, 'MULTIPLE_DROPDOWN_FOUND_ERROR': { 'zh-CN': '同时发现了多个下拉列表开关, 无法确定下拉列表所对应的视频, 刷新页面可能有帮助', 'zh-TW': '同時發現了多個下拉列表開關, 無法確定下拉列表所對應的影片, 重新載入頁面可能有幫助' }, 'TARGET_VIDEO_NOT_FOUND_ERROR': { 'zh-CN': '无法确定下拉列表所对应的视频, 请反馈该问题', 'zh-TW': '無法確定下拉列表所對應的影片, 請反饋該問題' }, 'REQUEST_TIMEOUT_ERROR': { 'zh-CN': '请求超时', 'zh-TW': '請求逾時' }, 'REQUEST_FAILED_ERROR': { 'zh-CN': '请求失败', 'zh-TW': '請求失敗' }, 'INTRO_AND_UPPER_UID_NOT_FOUND_ERROR': { 'zh-CN': '无法获取某个失效视频的简介和UP主UID, 切换至按最近收藏排序可能有帮助', 'zh-TW': '無法獲取某個失效影片的簡介和UP主UID, 切換至按最近收藏排序可能有幫助' }, 'UNKNOWN_ERROR': { 'zh-CN': '发生未知错误, 请反馈该问题', 'zh-TW': '發生未知錯誤, 請反饋該問題' }, }; const preferredLanguage = getPreferredLanguage(); const favlistURLRegex = /https:\/\/space\.bilibili\.com\/\d+\/favlist.*/; const BVFromURLRegex = /video\/(\w{12})/; const coverFromURLRegex = /\/\/([^@]*)@/; let onFavlistPage = false; let newFreshSpace; const favlistObserver = new MutationObserver((mutations, observer) => { if (document.querySelector('div.favlist-main')) { observer.disconnect(); newFreshSpace = true; biliCardDropdownPopperObserver.observe(document.body, { childList: true, attributes: false, characterData: false }); return; } if (document.querySelector('div.fav-content.section')) { observer.disconnect(); newFreshSpace = false; favContentSectionObserver.observe(document.querySelector('div.fav-content.section'), { characterData: false, attributeFilter: ['class'] }); return; } }); const biliCardDropdownPopperObserver = new MutationObserver(mutations => { for (const mutation of mutations) { for (const addedNode of mutation.addedNodes) { if (addedNode.nodeType === 1 && addedNode.classList.contains('bili-card-dropdown-popper')) { mainNewFreshSpace(addedNode); return; } } } }); const favContentSectionObserver = new MutationObserver(mutations => { for (const mutation of mutations) { if (!mutation.target.classList.contains('loading')) { 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 (favlistURLRegex.test(location.href)) { if (!onFavlistPage) { onFavlistPage = true; favlistObserver.observe(document.body, { subtree: true, childList: true, attributes: false, characterData: false }); } } else { if (onFavlistPage) { onFavlistPage = false; favlistObserver.disconnect(); biliCardDropdownPopperObserver.disconnect(); 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 mainNewFreshSpace(divDropdownPopper) { try { const divDropdowns = document.querySelectorAll('.bili-card-dropdown--visible'); if (divDropdowns.length !== 1) { 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(divDropdowns[0])) { divTargetVideo = item; break; } } } if (!divTargetVideo) { addMessage(getLocalizedText('TARGET_VIDEO_NOT_FOUND_ERROR')); return; } let disabled = false; if (!divTargetVideo.querySelector('.bili-cover-card__stats')) { disabled = true; } const BV = divDropdowns[0].parentNode.querySelector('a').getAttribute('href').match(BVFromURLRegex)[1]; const dropdownJump = document.createElement('div'); dropdownJump.classList.add('bili-card-dropdown-popper__item'); dropdownJump.textContent = getLocalizedText('DROPDOWN_JUMP'); dropdownJump.addEventListener('click', () => { try { divDropdownPopper.classList.remove('visible'); GM_openInTab(`https://www.biliplus.com/video/${BV}`, { active: disabled, insert: false, setParent: true }); GM_openInTab(`https://xbeibeix.com/video/${BV}`, { insert: false, setParent: true }); GM_openInTab(`https://www.jijidown.com/video/${BV}`, { insert: false, setParent: true }); } catch (error) { catchUnknownError(error); } }); divDropdownPopper.appendChild(dropdownJump); if (!disabled) { const dropdownCover = document.createElement('div'); dropdownCover.classList.add('bili-card-dropdown-popper__item'); dropdownCover.textContent = getLocalizedText('DROPDOWN_COVER'); dropdownCover.addEventListener('click', () => { try { divDropdownPopper.classList.remove('visible'); GM_openInTab(`https://${divTargetVideo.querySelector('img').getAttribute('src').match(coverFromURLRegex)[1]}`, { active: true, insert: true, setParent: true }); } catch (error) { catchUnknownError(error); } }); divDropdownPopper.appendChild(dropdownCover); } } catch (error) { catchUnknownError(error); } } async function main() { try { let medias; if (document.querySelectorAll('li.small-item.disabled').length) { const fid = document.querySelector('.fav-item.cur').getAttribute('fid'); const pn = parseInt(document.querySelector('li.be-pager-item-active').innerText, 10); 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=20&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'))) }); }); medias = response.response.data.medias; } document.querySelectorAll('li.small-item').forEach(li => { try { const ul = li.querySelector('ul.be-dropdown-menu'); if (!ul.lastElementChild.classList.contains('added')) { ul.lastElementChild.classList.add('be-dropdown-item-delimiter'); const BV = li.getAttribute('data-aid'); const as = li.querySelectorAll('a'); let disabled = false; if (li.classList.contains('disabled')) { li.classList.remove('disabled'); as[0].classList.remove('disabled'); disabled = true; } const dropdownJump = document.createElement('li'); dropdownJump.className = 'be-dropdown-item added'; dropdownJump.textContent = getLocalizedText('DROPDOWN_JUMP'); dropdownJump.addEventListener('click', () => { try { GM_openInTab(`https://www.biliplus.com/video/${BV}`, { active: disabled, insert: false, setParent: true }); GM_openInTab(`https://xbeibeix.com/video/${BV}`, { insert: false, setParent: true }); GM_openInTab(`https://www.jijidown.com/video/${BV}`, { insert: false, setParent: true }); } catch (error) { catchUnknownError(error); } }); ul.appendChild(dropdownJump); if (!disabled) { const dropdownCover = document.createElement('li'); dropdownCover.className = 'be-dropdown-item added'; dropdownCover.textContent = getLocalizedText('DROPDOWN_COVER'); dropdownCover.addEventListener('click', () => { try { GM_openInTab(`https://${li.querySelector('img').getAttribute('src').match(coverFromURLRegex)[1]}`, { active: true, insert: true, setParent: true }); } catch (error) { catchUnknownError(error); } }); ul.appendChild(dropdownCover); } if (disabled) { try { const media = medias.find(m => m.bvid === BV); as[1].textContent = media.intro; as[1].setAttribute('title', media.intro); const dropdownSpace = document.createElement('li'); dropdownSpace.className = 'be-dropdown-item added'; dropdownSpace.textContent = getLocalizedText('DROPDOWN_SPACE'); dropdownSpace.addEventListener('click', () => { try { GM_openInTab(`https://space.bilibili.com/${media.upper.mid}`, { active: true, insert: true, setParent: true }); } catch (error) { catchUnknownError(error); } }); ul.appendChild(dropdownSpace); } catch (error) { addMessage(getLocalizedText('INTRO_AND_UPPER_UID_NOT_FOUND_ERROR')); addMessage(error.stack, true); console.error(error); } } } } catch (error) { catchUnknownError(error); } }); } catch (error) { catchUnknownError(error); } } 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.padding = newFreshSpace ? '2px 0' : '2px'; p.style.fontSize = `${px}px`; p.style.lineHeight = '1.5'; document.querySelector(newFreshSpace ? 'div.favlist-aside' : 'div.fav-sidenav').appendChild(p); p.scrollIntoView({ behavior: 'instant', block: 'nearest' }); } function catchUnknownError(error) { addMessage(getLocalizedText('UNKNOWN_ERROR')); addMessage(error.stack, true); console.error(error); } })();