// ==UserScript== // @name 哔哩哔哩视频页面常驻显示AV/BV号[已完全重构,支持显示分P标题] // @namespace ckylin-bilibili-display-video-id // @version 1.2 // @description 始终在哔哩哔哩视频页面标题下方显示当前视频号,默认显示AV号,右键切换为BV号,单击弹窗可复制链接 // @author CKylinMC // @match https://www.bilibili.com/video* // @grant unsafeWindow // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @license GPLv3 License // @downloadURL none // ==/UserScript== (function () { const wait = (t) => new Promise(r => setTimeout(r, t)); const log = (...m) => console.log('[ShowAV]', ...m); const config = { showAv: true, defaultAv: true, showPn: true, }; const menuId = { showAv: -1, defaultAv: -1, showPn: -1 }; let infos = {}; async function initScript() { if (menuId.showAv != -1) GM_unregisterMenuCommand(menuId.showAv); if (menuId.defaultAv != -1) GM_unregisterMenuCommand(menuId.defaultAv); if (menuId.showPn != -1) GM_unregisterMenuCommand(menuId.showPn); if (!(await GM_getValue("inited"))) { await GM_setValue("showAv", true); await GM_setValue("defaultAv", true); await GM_setValue("showPn", true); await GM_setValue("inited", true); } if ((await GM_getValue("showAv"))) { config.showAv = true; menuId.showAv = GM_registerMenuCommand("隐藏视频编号[当前显示]", async () => { await GM_setValue("showAv", false); initScript(); tryInject(); }); } else { config.showAv = false; menuId.showAv = GM_registerMenuCommand("显示视频编号[当前隐藏]", async () => { await GM_setValue("showAv", true); initScript(); tryInject(); }); } if ((await GM_getValue("defaultAv"))) { config.defaultAv = true; menuId.defaultAv = GM_registerMenuCommand("默认显示BV号[当前显示av号]", async () => { await GM_setValue("defaultAv", false); initScript(); tryInject(); }); } else { config.defaultAv = false; menuId.defaultAv = GM_registerMenuCommand("默认显示av号[当前显示BV号]", async () => { await GM_setValue("defaultAv", true); initScript(); tryInject(); }); } if ((await GM_getValue("showPn"))) { config.showPn = true; menuId.showPn = GM_registerMenuCommand("隐藏视频分P信息[当前显示]", async () => { await GM_setValue("showPn", false); initScript(); tryInject(); }); } else { config.showPn = false; menuId.showPn = GM_registerMenuCommand("显示视频分P信息[当前隐藏]", async () => { await GM_setValue("showPn", true); initScript(); tryInject(); }); } } function videoInitInfoHandler(e) { if (e.data.command && e.data.pageData && e.data.command == "sendInitData") { infos = e.data.pageData; tryInject(true); } } async function playerReady() { let i = 50; while (--i >= 0) { await wait(100); if (!('player' in unsafeWindow)) continue; if (!('isInitialized' in unsafeWindow.player)) continue; if (!unsafeWindow.player.isInitialized()) continue; return true; } return false; } async function waitForDom(q) { let i = 50; let dom; while (--i >= 0) { if (dom = document.querySelector(q)) break; await wait(100); } return dom; } function getUrlParam(key) { return (new URL(location.href)).searchParams.get(key); } function getOrNew(id, parent) { let target = document.querySelector("#" + id); if (!target) { target = document.createElement("span"); target.id = id; target.style.marginLeft = "16px"; parent.appendChild(target); } return target; } async function getPlayerSeeks() { const video = await waitForDom(".bilibili-player-video video"); let seconds = 0; if (video) { seconds = Math.floor(video.currentTime); } if (seconds == 0) { let fromParam = getUrlParam("t") || 0; return fromParam; } else return seconds; } async function tryInject(fromHandler) { if (fromHandler && !config.showAv && !config.showPn) return log('Terminated because no option is enabled.'); if (!(await playerReady())) return log('Can not load player in time.'); const av_root = await waitForDom(".video-data"); if (!av_root) return log('Can not load info-bar in time.'); const av_span = getOrNew("bilibiliShowAV", av_root); if (config.showAv) { if(config.defaultAv) av_span.innerText = 'av' + infos.aid; else av_span.innerText = infos.bvid; av_span.oncontextmenu = e => { if (e.target.innerText.startsWith('av')) e.target.innerText = infos.bvid; else av_span.innerText = 'av' + infos.aid; e.preventDefault(); } av_span.onclick = async e => { let url = new URL(location.protocol + "//" + location.hostname + location.pathname); infos.p == 1 || url.searchParams.append("p", infos.p); let t = await getPlayerSeeks(); if (t && t != "0") url.searchParams.append("t", t); prompt("当前视频地址:", url); } } else av_span.remove(); const pn_span = getOrNew("bilibiliShowPN", av_root); if (config.showPn) { const videoData = infos.videoData; if (!videoData) return; let part = { part: 'P' + infos.p } try { part = videoData.pages[infos.p - 1]; } catch (e) { part = videoData.pages[0]; } const currentPageNum = `P ${infos.p}/${videoData.videos}`; const currentPageName = `《${part.part}》` pn_span.style.textOverflow = "ellipsis"; pn_span.style.whiteSpace = "nowarp"; pn_span.style.overflow = "hidden"; pn_span.title = currentPageNum + "\n" + currentPageName pn_span.innerText = currentPageNum + " " + currentPageName; } else pn_span.remove(); } initScript(); unsafeWindow.addEventListener("message", videoInitInfoHandler); })();