// ==UserScript== // @name bilibili favlist hidden video detection // @name:zh-CN 哔哩哔哩(B站|Bilibili)收藏夹Fix(隐藏视频检测) // @name:zh-TW 嗶哩嗶哩(B站|Bilibili)收藏夾Fix(隱藏影片檢測) // @namespace http://tampermonkey.net/ // @version 5 // @description detect videos in favlist that only visiable to upper // @description:zh-CN 检测收藏夹中被up主设置为仅自己可见的视频 // @description:zh-TW 檢測收藏夾中被上傳者設定為僅自己可見的影片 // @author YTB0710 // @match https://space.bilibili.com/* // @connect api.bilibili.com // @grant GM_xmlhttpRequest // @grant GM_cookie // @grant GM_openInTab // @grant GM_setValue // @grant GM_getValue // @downloadURL none // ==/UserScript== (function () { 'use strict'; const localizedText = { 'UPDATES': { 'zh-CN': '更新内容:
新增: 适配新版个人空间
其他: 优化各个控件的展示效果', 'zh-TW': '更新內容:
新增: 適配新版個人主頁
其他: 優化各個控件的顯示效果' }, 'INPUT_AV_OR_BV_HERE': { 'zh-CN': '在此输入av号或bv号', 'zh-TW': '在此輸入av號或bv號' }, 'DETECT_HIDDEN_VIDEO_WITH_PROMPT': { 'zh-CN': '检测隐藏视频(先刷新页面)', 'zh-TW': '檢測隱藏影片(先重新載入頁面)' }, 'DETECT_HIDDEN_VIDEO': { 'zh-CN': '检测隐藏视频', 'zh-TW': '檢測隱藏影片' }, 'GET_VIDEO_INFO_WITH_PROMPT': { 'zh-CN': '查询视频信息(输入bv号)', 'zh-TW': '查詢影片資訊(輸入bv號)' }, 'GET_VIDEO_INFO': { 'zh-CN': '查询视频信息', 'zh-TW': '查詢影片資訊' }, 'REMOVE_VIDEO_WITH_PROMPT': { 'zh-CN': '取消收藏(输入av号)', 'zh-TW': '取消收藏(輸入av號)' }, 'REMOVE_VIDEO': { 'zh-CN': '取消收藏', 'zh-TW': '取消收藏' }, 'ADD_VIDEO_WITH_PROMPT': { 'zh-CN': '添加收藏(输入av号)', 'zh-TW': '新增收藏(輸入av號)' }, 'ADD_VIDEO': { 'zh-CN': '添加收藏', 'zh-TW': '新增收藏' }, 'AV': { 'zh-CN': 'av号', 'zh-TW': 'av號' }, 'BV': { 'zh-CN': 'bv号', 'zh-TW': 'bv號' }, 'INPUT_AV': { 'zh-CN': '请输入av号', 'zh-TW': '請輸入av號' }, 'INPUT_BV': { 'zh-CN': '请输入bv号', 'zh-TW': '請輸入bv號' }, 'NO_HIDDEN_VIDEO_ON_THIS_PAGE': { 'zh-CN': '本页没有隐藏的视频', 'zh-TW': '本頁沒有隱藏的影片' }, 'POSITION_ON_THIS_PAGE_WITH_PROMPT': { 'zh-CN': '在本页的位置(从1开始)', 'zh-TW': '在本頁的位置(從1開始)' }, 'POSITION_ON_THIS_PAGE': { 'zh-CN': '在本页的位置', 'zh-TW': '在本頁的位置' }, 'API_RESPONSE_CONTENT': { 'zh-CN': 'b站接口响应内容', 'zh-TW': 'b站介面回應內容' }, 'REFRESH_PAGE_IF_ERROR': { 'zh-CN': '如果出现问题, 请刷新页面后重试', 'zh-TW': '如果出現問題, 請重新載入頁面後再試' }, 'COOKIE_READ_ERROR': { 'zh-CN': '无法读取cookie, 请更新tampermonkey, 前往控制台查看错误信息', 'zh-TW': '無法讀取cookie, 請更新tampermonkey, 前往控制台查看錯誤資訊' }, 'VIDEOS_PER_PAGE': { 'zh-CN': '每页展示视频数量', 'zh-TW': '每頁顯示影片數量' }, 'VIDEOS_PER_PAGE_WITH_PROMPT': { 'zh-CN': '每页最多可以展示的视频数量(一般为36或40)', 'zh-TW': '每頁最多可以顯示的影片數量(一般為36或40)' }, 'INVALID_VIDEOS_PER_PAGE_ERROR': { 'zh-CN': '每页展示视频数量不正确, 请重新输入', 'zh-TW': '每頁顯示影片數量不正確, 請重新輸入' }, 'CHECK_VIDEOS_PER_PAGE_AND_REFRESH_PAGE_IF_ERROR': { 'zh-CN': '如果出现问题, 请检查每页展示视频数量是否正确, 如果无误, 请刷新页面后重试', 'zh-TW': '如果出現問題, 請檢查每頁顯示影片數量是否正確, 如果無誤, 請重新載入頁面後再試' }, 'CHECK_VIDEOS_PER_PAGE_AND_RETRY': { 'zh-CN': '请检查预设的每页展示视频数量是否正确, 然后再次点击按钮', 'zh-TW': '請檢查預設的每頁顯示影片數量是否正確, 然後再次點擊按鈕' }, 'INPUT_VIDEOS_PER_PAGE_AND_RETRY': { 'zh-CN': '请手动设置每页展示视频数量, 然后再次点击按钮', 'zh-TW': '請手動設定每頁顯示影片數量, 然後再次點擊按鈕' }, 'FID_NOT_FOUND_ERROR': { 'zh-CN': '无法获取当前收藏夹的fid, 请刷新页面后重试', 'zh-TW': '無法獲取當前收藏夾的fid, 請重新載入頁面後再試' }, }; const preferredLanguage = getPreferredLanguage(); const currentVersion = 5; const avRegex = /^[1-9]\d*$/; const bvRegex = /^BV[A-Za-z0-9]{10}$/; const startsWithAVRegex = /^av/i; const favlistURLRegex = /https:\/\/space\.bilibili\.com\/\d+\/favlist.*/; const pagenationCountRegex = /共 (\d+) 页 \/ (\d+) 个/; const fidFromUrlRegex = /fid=(\d+)/; const bvFromUrlRegex = /video\/(\w{12})/; let onFavlistPage = false; 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]; } const sideObserver = new MutationObserver(function (mutations, observer) { for (const mutation of mutations) { if (mutation.type === 'childList') { if (document.querySelector('div.favlist-aside')) { observer.disconnect(); mainNewFreshSpace(); return; } if (document.querySelector('div.fav-sidenav')) { observer.disconnect(); 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; sideObserver.observe(document.body, { subtree: true, childList: true }); } } else { if (onFavlistPage) { onFavlistPage = false; sideObserver.disconnect(); } } } function mainNewFreshSpace() { let videosPerPage; const storedVersion = GM_getValue('version', 0); let displayUpdate = false; if (storedVersion !== currentVersion) { GM_setValue('version', currentVersion); if (storedVersion) { displayUpdate = true; } } const usageCountNewFreshSpace = GM_getValue('usageCountNewFreshSpace', 0); const displayPrompt = usageCountNewFreshSpace < 10 ? '_WITH_PROMPT' : ''; if (displayPrompt) { GM_setValue('usageCountNewFreshSpace', usageCountNewFreshSpace + 1); } const favlistAside = document.querySelector('div.favlist-aside'); const divControls = document.createElement('div'); divControls.style.padding = '2px 0'; favlistAside.appendChild(divControls); const divVideosPerPage = document.createElement('div'); divVideosPerPage.style.padding = '2px 0'; divControls.appendChild(divVideosPerPage); const labelA = document.createElement('label'); labelA.innerText = getLocalizedText('VIDEOS_PER_PAGE' + displayPrompt); labelA.style.lineHeight = '1'; divVideosPerPage.appendChild(labelA); const inputTextA = document.createElement('input'); inputTextA.type = 'text'; inputTextA.style.boxSizing = 'content-box'; inputTextA.style.height = '16px'; inputTextA.style.width = '20px'; inputTextA.style.padding = '4px'; inputTextA.style.border = '1px solid #ccc'; inputTextA.style.borderRadius = '3px'; inputTextA.style.fontSize = '16px'; inputTextA.style.lineHeight = '1'; labelA.insertAdjacentElement('beforeend', inputTextA); const divInputTextB = document.createElement('div'); divInputTextB.style.padding = '2px 0'; divControls.appendChild(divInputTextB); const inputTextB = document.createElement('input'); inputTextB.type = 'text'; inputTextB.style.boxSizing = 'content-box'; inputTextB.style.height = '16px'; inputTextB.style.width = '170px'; inputTextB.style.padding = '4px'; inputTextB.style.border = '1px solid #ccc'; inputTextB.style.borderRadius = '3px'; inputTextB.style.fontSize = '16px'; inputTextB.style.lineHeight = '1'; if (displayPrompt) { inputTextB.placeholder = getLocalizedText('INPUT_AV_OR_BV_HERE'); } divInputTextB.appendChild(inputTextB); const divButtonA = document.createElement('div'); divButtonA.style.padding = '2px 0'; divControls.appendChild(divButtonA); const buttonA = document.createElement('button'); buttonA.type = 'button'; buttonA.innerText = getLocalizedText('DETECT_HIDDEN_VIDEO' + displayPrompt); buttonA.style.padding = '4px'; buttonA.style.border = '1px solid #ccc'; buttonA.style.borderRadius = '3px'; buttonA.style.fontSize = '16px'; buttonA.style.lineHeight = '1'; buttonA.style.cursor = 'pointer'; buttonA.addEventListener('click', function () { clearMessage(); const fidFromUrlMatch = location.href.match(fidFromUrlRegex); let fid; if (fidFromUrlMatch) { fid = fidFromUrlMatch[1]; } else { addMessage(getLocalizedText('FID_NOT_FOUND_ERROR')); return; } const divVideos = document.querySelectorAll('div.bili-video-card__wrap'); const spanPagenationGoCount = document.querySelector('span.vui_pagenation-go__count'); if (spanPagenationGoCount) { videosPerPage = parseInt(inputTextA.value, 10); if (isNaN(videosPerPage)) { if (divVideos.length <= 36) { inputTextA.value = 36; } else if (divVideos.length <= 40) { inputTextA.value = 40; } else { addMessage(getLocalizedText('INPUT_VIDEOS_PER_PAGE_AND_RETRY')); return; } addMessage(getLocalizedText('CHECK_VIDEOS_PER_PAGE_AND_RETRY')); return; } const pagenationCountMatch = spanPagenationGoCount.innerText.match(pagenationCountRegex); const totalPages = parseInt(pagenationCountMatch[1], 10); const totalVideos = parseInt(pagenationCountMatch[2], 10); if (videosPerPage < Math.ceil(totalVideos / totalPages) || (videosPerPage > Math.floor((totalVideos - 1) / (totalPages - 1)))) { addMessage(getLocalizedText('INVALID_VIDEOS_PER_PAGE_ERROR')); return; } } addMessage(getLocalizedText('CHECK_VIDEOS_PER_PAGE_AND_REFRESH_PAGE_IF_ERROR'), 11); GM_xmlhttpRequest({ method: 'GET', url: `https://api.bilibili.com/x/v3/fav/resource/ids?media_id=${fid}`, responseType: 'json', onload: function (response) { const datas = response.response.data; let currentPage; const pagenation = document.querySelector('button.vui_pagenation--btn-num.vui_button--active'); if (!pagenation) { currentPage = 1; } else { currentPage = parseInt(pagenation.innerText, 10); } const startIndex = (currentPage - 1) * videosPerPage; const currentPageExpectedDatas = datas.slice(startIndex, startIndex + videosPerPage); const currentPageActualBVs = Array.from(divVideos).map(divVideo => divVideo.querySelector('a.bili-cover-card').getAttribute('href').match(bvFromUrlRegex)[1]); const hiddenDatas = currentPageExpectedDatas.filter(data => !currentPageActualBVs.includes(data.bvid)); if (!hiddenDatas.length) { addMessage(getLocalizedText('NO_HIDDEN_VIDEO_ON_THIS_PAGE')); return; } hiddenDatas.forEach(hiddenData => { addMessage(`${getLocalizedText('POSITION_ON_THIS_PAGE' + displayPrompt)}: ${currentPageExpectedDatas.findIndex(data => data.bvid === hiddenData.bvid) + 1}`); addMessage(`${getLocalizedText('AV')}: ${hiddenData.id}`); addMessage(`${getLocalizedText('BV')}: ${hiddenData.bvid}`); }); } }); }); divButtonA.appendChild(buttonA); const divButtonB = document.createElement('div'); divButtonB.style.padding = '2px 0'; divControls.appendChild(divButtonB); const buttonB = document.createElement('button'); buttonB.type = 'button'; buttonB.innerText = getLocalizedText('GET_VIDEO_INFO' + displayPrompt); buttonB.style.padding = '4px'; buttonB.style.border = '1px solid #ccc'; buttonB.style.borderRadius = '3px'; buttonB.style.fontSize = '16px'; buttonB.style.lineHeight = '1'; buttonB.style.cursor = 'pointer'; buttonB.addEventListener('click', function () { clearMessage(); const bv = inputTextB.value; if (!bvRegex.test(bv)) { addMessage(getLocalizedText('INPUT_BV')); return; } GM_openInTab(`https://www.biliplus.com/video/${bv}`, { active: true, 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 }); }); divButtonB.appendChild(buttonB); const divButtonC = document.createElement('div'); divButtonC.style.padding = '2px 0'; divControls.appendChild(divButtonC); const buttonC = document.createElement('button'); buttonC.type = 'button'; buttonC.innerText = getLocalizedText('REMOVE_VIDEO' + displayPrompt); buttonC.style.padding = '4px'; buttonC.style.border = '1px solid #ccc'; buttonC.style.borderRadius = '3px'; buttonC.style.fontSize = '16px'; buttonC.style.lineHeight = '1'; buttonC.style.cursor = 'pointer'; buttonC.addEventListener('click', function () { clearMessage(); GM_cookie.list({ name: 'bili_jct' }, function (cookies, error) { if (!error) { let av = inputTextB.value; if (startsWithAVRegex.test(av)) { av = av.slice(2); } if (!avRegex.test(av)) { addMessage(getLocalizedText('INPUT_AV')); return; } const fidFromUrlMatch = location.href.match(fidFromUrlRegex); let fid; if (fidFromUrlMatch) { fid = fidFromUrlMatch[1]; } else { addMessage(getLocalizedText('FID_NOT_FOUND_ERROR')); return; } const csrf = cookies[0].value; const data = `resources=${av}%3A2&media_id=${fid}&platform=web&csrf=${csrf}`; GM_xmlhttpRequest({ method: 'POST', url: 'https://api.bilibili.com/x/v3/fav/resource/batch-del', data: data, headers: { 'Content-Length': data.length, 'Content-Type': 'application/x-www-form-urlencoded' }, onload: function (response) { const json = response.response; addMessage(`${getLocalizedText('API_RESPONSE_CONTENT')}:`); addMessage(json, 11); } }); } else { console.error(error); addMessage(getLocalizedText('COOKIE_READ_ERROR')); } }); }); divButtonC.appendChild(buttonC); const divButtonD = document.createElement('div'); divButtonD.style.padding = '2px 0'; divControls.appendChild(divButtonD); const buttonD = document.createElement('button'); buttonD.type = 'button'; buttonD.innerText = getLocalizedText('ADD_VIDEO' + displayPrompt); buttonD.style.padding = '4px'; buttonD.style.border = '1px solid #ccc'; buttonD.style.borderRadius = '3px'; buttonD.style.fontSize = '16px'; buttonD.style.lineHeight = '1'; buttonD.style.cursor = 'pointer'; buttonD.addEventListener('click', function () { clearMessage(); GM_cookie.list({ name: 'bili_jct' }, function (cookies, error) { if (!error) { let av = inputTextB.value; if (startsWithAVRegex.test(av)) { av = av.slice(2); } if (!avRegex.test(av)) { addMessage(getLocalizedText('INPUT_AV')); return; } const fidFromUrlMatch = location.href.match(fidFromUrlRegex); let fid; if (fidFromUrlMatch) { fid = fidFromUrlMatch[1]; } else { addMessage(getLocalizedText('FID_NOT_FOUND_ERROR')); return; } const csrf = cookies[0].value; const data = `rid=${av}&type=2&add_media_ids=${fid}&csrf=${csrf}`; GM_xmlhttpRequest({ method: 'POST', url: 'https://api.bilibili.com/x/v3/fav/resource/deal', data: data, headers: { 'Content-Length': data.length, 'Content-Type': 'application/x-www-form-urlencoded' }, onload: function (response) { const json = response.response; addMessage(`${getLocalizedText('API_RESPONSE_CONTENT')}:`); addMessage(json, 11); } }); } else { console.error(error); addMessage(getLocalizedText('COOKIE_READ_ERROR')); } }); }); divButtonD.appendChild(buttonD); const divMessage = document.createElement('div'); divMessage.style.padding = '2px 0'; divMessage.style.lineHeight = '1.5'; divControls.appendChild(divMessage); if (displayUpdate) { setTimeout(() => { addMessage(getLocalizedText('UPDATES')); }, 300); } function addMessage(msg, px = 13) { 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 main() { const videosPerPage = 20; const storedVersion = GM_getValue('version', 0); let displayUpdate = false; if (storedVersion !== currentVersion) { GM_setValue('version', currentVersion); if (storedVersion) { displayUpdate = true; } } const usageCount = GM_getValue('usageCount', 0); const displayPrompt = usageCount < 10 ? '_WITH_PROMPT' : ''; if (displayPrompt) { GM_setValue('usageCount', usageCount + 1); } const favSidenav = document.querySelector('div.fav-sidenav'); favSidenav.querySelector('a.watch-later').style.borderBottom = '1px solid #eee'; const divControls = document.createElement('div'); divControls.style.borderTop = '1px solid #e4e9f0'; divControls.style.padding = '2px'; favSidenav.appendChild(divControls); const divInputText = document.createElement('div'); divInputText.style.padding = '2px'; divControls.appendChild(divInputText); const inputText = document.createElement('input'); inputText.type = 'text'; inputText.style.boxSizing = 'content-box'; inputText.style.height = '14px'; inputText.style.width = '150px'; inputText.style.padding = '3px'; inputText.style.border = '1px solid #ccc'; inputText.style.borderRadius = '3px'; inputText.style.fontSize = '14px'; inputText.style.lineHeight = '1'; if (displayPrompt) { inputText.placeholder = getLocalizedText('INPUT_AV_OR_BV_HERE'); } divInputText.appendChild(inputText); const divButtonA = document.createElement('div'); divButtonA.style.padding = '2px'; divControls.appendChild(divButtonA); const buttonA = document.createElement('button'); buttonA.type = 'button'; buttonA.innerText = getLocalizedText('DETECT_HIDDEN_VIDEO' + displayPrompt); buttonA.style.padding = '3px'; buttonA.style.border = '1px solid #ccc'; buttonA.style.borderRadius = '3px'; buttonA.style.fontSize = '14px'; buttonA.style.lineHeight = '1'; buttonA.style.cursor = 'pointer'; buttonA.addEventListener('click', function () { clearMessage(); addMessage(getLocalizedText('REFRESH_PAGE_IF_ERROR'), 10); const favNum = parseInt(document.querySelector('.fav-item.cur > span.num').innerText, 10); const pager = document.querySelector('li.be-pager-next'); let currentPageExpectedNum; if (pager && !pager.classList.contains('be-pager-disabled')) { currentPageExpectedNum = videosPerPage; } else { currentPageExpectedNum = favNum % videosPerPage; } const lis = document.querySelectorAll('li.small-item'); if (lis.length === currentPageExpectedNum) { addMessage(getLocalizedText('NO_HIDDEN_VIDEO_ON_THIS_PAGE')); return; } const fid = document.querySelector('.fav-item.cur').getAttribute('fid'); GM_xmlhttpRequest({ method: 'GET', url: `https://api.bilibili.com/x/v3/fav/resource/ids?media_id=${fid}`, responseType: 'json', onload: function (response) { const datas = response.response.data; let currentPage = 1; if (favNum > videosPerPage) { currentPage = parseInt(document.querySelector('li.be-pager-item-active').innerText, 10); } const startIndex = (currentPage - 1) * videosPerPage; const currentPageExpectedDatas = datas.slice(startIndex, startIndex + videosPerPage); const currentPageActualBVs = Array.from(lis).map(li => li.getAttribute('data-aid')); const hiddenDatas = currentPageExpectedDatas.filter(data => !currentPageActualBVs.includes(data.bvid)); hiddenDatas.forEach(hiddenData => { addMessage(`${getLocalizedText('POSITION_ON_THIS_PAGE' + displayPrompt)}: ${currentPageExpectedDatas.findIndex(data => data.bvid === hiddenData.bvid) + 1}`); addMessage(`${getLocalizedText('AV')}: ${hiddenData.id}`); addMessage(`${getLocalizedText('BV')}: ${hiddenData.bvid}`); }); } }); }); divButtonA.appendChild(buttonA); const divButtonB = document.createElement('div'); divButtonB.style.padding = '2px'; divControls.appendChild(divButtonB); const buttonB = document.createElement('button'); buttonB.type = 'button'; buttonB.innerText = getLocalizedText('GET_VIDEO_INFO' + displayPrompt); buttonB.style.padding = '3px'; buttonB.style.border = '1px solid #ccc'; buttonB.style.borderRadius = '3px'; buttonB.style.fontSize = '14px'; buttonB.style.lineHeight = '1'; buttonB.style.cursor = 'pointer'; buttonB.addEventListener('click', function () { clearMessage(); const bv = inputText.value; if (!bvRegex.test(bv)) { addMessage(getLocalizedText('INPUT_BV')); return; } GM_openInTab(`https://www.biliplus.com/video/${bv}`, { active: true, 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 }); }); divButtonB.appendChild(buttonB); const divButtonC = document.createElement('div'); divButtonC.style.padding = '2px'; divControls.appendChild(divButtonC); const buttonC = document.createElement('button'); buttonC.type = 'button'; buttonC.innerText = getLocalizedText('REMOVE_VIDEO' + displayPrompt); buttonC.style.padding = '3px'; buttonC.style.border = '1px solid #ccc'; buttonC.style.borderRadius = '3px'; buttonC.style.fontSize = '14px'; buttonC.style.lineHeight = '1'; buttonC.style.cursor = 'pointer'; buttonC.addEventListener('click', function () { clearMessage(); GM_cookie.list({ name: 'bili_jct' }, function (cookies, error) { if (!error) { let av = inputText.value; if (startsWithAVRegex.test(av)) { av = av.slice(2); } if (!avRegex.test(av)) { addMessage(getLocalizedText('INPUT_AV')); return; } const fid = document.querySelector('.fav-item.cur').getAttribute('fid'); const csrf = cookies[0].value; const data = `resources=${av}%3A2&media_id=${fid}&platform=web&csrf=${csrf}`; GM_xmlhttpRequest({ method: 'POST', url: 'https://api.bilibili.com/x/v3/fav/resource/batch-del', data: data, headers: { 'Content-Length': data.length, 'Content-Type': 'application/x-www-form-urlencoded' }, onload: function (response) { const json = response.response; addMessage(`${getLocalizedText('API_RESPONSE_CONTENT')}:`); addMessage(json, 10); } }); } else { console.error(error); addMessage(getLocalizedText('COOKIE_READ_ERROR')); } }); }); divButtonC.appendChild(buttonC); const divButtonD = document.createElement('div'); divButtonD.style.padding = '2px'; divControls.appendChild(divButtonD); const buttonD = document.createElement('button'); buttonD.type = 'button'; buttonD.innerText = getLocalizedText('ADD_VIDEO' + displayPrompt); buttonD.style.padding = '3px'; buttonD.style.border = '1px solid #ccc'; buttonD.style.borderRadius = '3px'; buttonD.style.fontSize = '14px'; buttonD.style.lineHeight = '1'; buttonD.style.cursor = 'pointer'; buttonD.addEventListener('click', function () { clearMessage(); GM_cookie.list({ name: 'bili_jct' }, function (cookies, error) { if (!error) { let av = inputText.value; if (startsWithAVRegex.test(av)) { av = av.slice(2); } if (!avRegex.test(av)) { addMessage(getLocalizedText('INPUT_AV')); return; } const fid = document.querySelector('.fav-item.cur').getAttribute('fid'); const csrf = cookies[0].value; const data = `rid=${av}&type=2&add_media_ids=${fid}&csrf=${csrf}`; GM_xmlhttpRequest({ method: 'POST', url: 'https://api.bilibili.com/x/v3/fav/resource/deal', data: data, headers: { 'Content-Length': data.length, 'Content-Type': 'application/x-www-form-urlencoded' }, onload: function (response) { const json = response.response; addMessage(`${getLocalizedText('API_RESPONSE_CONTENT')}:`); addMessage(json, 10); } }); } else { console.error(error); addMessage(getLocalizedText('COOKIE_READ_ERROR')); } }); }); divButtonD.appendChild(buttonD); const divMessage = document.createElement('div'); divMessage.style.padding = '2px'; divMessage.style.lineHeight = '1.5'; divControls.appendChild(divMessage); if (displayUpdate) { setTimeout(() => { addMessage(getLocalizedText('UPDATES')); }, 300); } function addMessage(msg, px = 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); } } } })();