您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
优化未登录(不可用)情况下的移动网页端的使用体验 | V0.9 更新评论模块的版本
// ==UserScript== // @name Bilibili - 优化未登录(不可用)情况下的移动网页端 // @namespace https://bilibili.com/ // @version 0.9 // @description 优化未登录(不可用)情况下的移动网页端的使用体验 | V0.9 更新评论模块的版本 // @license GPL-3.0 // @author DD1969 // @match https://m.bilibili.com/* // @icon https://www.bilibili.com/favicon.ico // @require https://update.gf.qytechs.cn/scripts/475332/1250588/spark-md5.js // @require https://update.gf.qytechs.cn/scripts/510239/1454424/viewer.js // @require https://update.gf.qytechs.cn/scripts/524844/1606386/bilibili-mobile-comment-module.js // @require https://update.gf.qytechs.cn/scripts/512576/1464552/inject-viewerjs-style.js // @require https://update.gf.qytechs.cn/scripts/512574/1464548/inject-bilibili-comment-style.js // @grant none // @run-at document-end // ==/UserScript== (async function() { 'use strict'; // no need to continue this script if user already logged in if (document.cookie.includes('DedeUserID')) return; const blacklist = []; // regular expressions const re = { home: /m\.bilibili\.com\/$|m\.bilibili\.com\/channel\/v\/.*/, video: /m\.bilibili\.com\/video\/.*/, search: /m\.bilibili\.com\/search.*/, space: /m\.bilibili\.com\/space\/.*/, dynamic: /m\.bilibili\.com\/dynamic\/.*/, opus: /m\.bilibili\.com\/opus\/.*/, topicDetail: /m\.bilibili\.com\/topic-detail.*/, } // make sure the document is ready await new Promise(resolve => { const timer = setInterval(() => { if (document.head && document.body) { clearInterval(timer); resolve(); } }, 50); }); // search and remove elements constantly setupElementCleaner(); // add style patch addStyle(); // nav bar modifyNavBar(); // home page if (re.home.test(window.location.href)) modifyHomePage(); // video page if (re.video.test(window.location.href)) modifyVideoPage(); // search page if (re.search.test(window.location.href)) modifySearchPage(); // space page if (re.space.test(window.location.href)) modifySpacePage(); // dynamic page if (re.dynamic.test(window.location.href)) modifyDynamicPage(); // opus page if (re.opus.test(window.location.href)) modifyOpusPage(); // topic detail page if (re.topicDetail.test(window.location.href)) modifyTopicDetailPage(); // ------------ functions below ------------ function setupElementCleaner() { const selectors = []; // home page if (re.home.test(window.location.href)) { selectors.push(...[ '.m-nav-openapp', // 右上角的"下载App"按钮 '.m-navbar .face', // 右上角的用户头像 '.fixed-openapp', // 首页底部的打开App横条 '.v-card__stats', // 视频卡片的数据信息 '.reserve-float-btn', // 首页底部的浮动弹窗 ]); } // video page if (re.video.test(window.location.href)) { selectors.push(...[ '.m-nav-openapp', // 右上角的"下载App"按钮 '.m-navbar .face', // 右上角的用户头像 '.video-natural-search .fixed-wrapper', // 顶部遮挡video元素的整个区域 '.m-video-related .list-custom-slot .m-open-app', // 相关视频底部的打开App横条 '.openapp-dialog', // 底部弹出的"浏览方式" '.caution-dialog', // 底部弹出的"友情提示" '.play-page-gotop', // 回到顶部按钮 '.reserve-float-btn', // 底部的浮动弹窗 '.fixed-openapp', // URL带'unique_k'参数时右下角才会出现的打开App按钮 '.gsl-callapp-dom', // 视频模块中阻碍点击并唤起app的元素 'm-open-app.m-video-main-launchapp', // 从b23.tv打开时出现的打开App横条 '.m-video-info', // 从b23.tv打开时出现的视频标题、作者和简介 '.bottom-tab-header', // 从b23.tv打开时出现的下方相关视频header '.m-video-part', // 从b23.tv打开时出现的视频分P模块#1 '.m-video-part-panel', // 从b23.tv打开时出现的视频分P模块#2 ]); } // space page if (re.space.test(window.location.href)) { selectors.push(...[ '.fixed-openapp', // 底部的打开App按钮 '.bili-dyn-item-header__following', // 动态右上方的关注按钮 '.dyn-orig-author__following', // 转发的动态的作者的关注按钮 ]); } // dynamic & opus page if (re.dynamic.test(window.location.href) || re.opus.test(window.location.href)) { selectors.push(...[ '.fixed-openapp', // 底部的打开App横条 '.dyn-header__following', // 动态右上方的关注按钮 '.dyn-share', // 若干分享按钮 '.openapp-dialog', // 底部弹出的"浏览方式" '.reserve-float-btn', // 底部的浮动弹窗 '.opus-module-author__action', // opus页右上角的关注按钮 '.stat-openApp', // opus页(原专栏页)底部的stat模块 ]); } // topic detail page if (re.topicDetail.test(window.location.href)) { selectors.push(...[ '.m-topic-float-openapp', // 底部的打开App按钮 ]); } // start cleaning setInterval(() => { for (const selector of selectors) { document.querySelectorAll(selector).forEach(element => element.remove()); } }, 100); } function addStyle() { // nav bar const navBarCSS = document.createElement('style'); navBarCSS.textContent = ` .m-navbar { position: relative !important; display: flex !important; justify-content: space-between; align-items: center; background: none !important; background-color: #FFFFFF !important; border-bottom: 1px solid #EEEEEE; } .nav-logo { display: flex; align-items: center; height: 100%; } .nav-logo img { height: 60%; } .nav-search { display: flex; flex-direction: column; justify-content: center; width: 200px; height: 28px; border: 1px solid #EEEEEE; border-radius: 16px; } .nav-search > svg { align-self: flex-end; margin-right: 8px; } `; document.head.appendChild(navBarCSS); // video page const videoPageCSS = document.createElement('style'); videoPageCSS.textContent = ` .video-share-loading-mask { position: absolute; top: 0; left: 0; display: none; justify-content: center; align-items: center; width: 100%; height: 100%; z-index: 1999; background-color: #000000; } .video-share-loading-mask-circle { width: 30px; height: 30px; border: 2px solid #000000; border-top-color: #ffffff; border-right-color: #ffffff; border-bottom-color: #ffffff; border-radius: 100%; animation: circle infinite 0.75s linear; } @keyframes circle { 0% { transform: rotate(0); } 100% { transform: rotate(360deg); } } .m-video-player { position: relative !important; top: initial !important; } .video-info { display: flex; flex-direction: column; padding: 20px 12px; } .video-info-title { font-size: 1.2rem; word-break: break-all; } .video-info-author { display: flex; align-items: center; margin-top: 16px; } .video-info-author-avatar { width: 32px; height: 32px; margin-right: 8px; border-radius: 100%; } .video-info-desc { color: #666666; font-size: 0.8rem; word-break: break-all; } .m-video-related { margin-top: 0 !important; padding: 24px 0; border-top: 1px dashed #aaa; border-bottom: 1px dashed #aaa; } .card-box { justify-content: space-between; } .card-box > .card { width: 49%; } .card-box .card .label, .card-box .card .open-app.weakened, .card-box .card .video-card .count { display: none !important; } .card-box .card .title { padding-top: 8px; padding-bottom: 16px; font-size: 0.8rem !important; word-break: break-all; } .gsl-top-return { transform: scale(0.5); } .gsl-buffer-app { display: none !important; } .gsl-control-btn.gsl-control-btn-quality { display: none !important; } .gsl-control-btn.gsl-control-btn-speed { display: flex !important; } .gsl-control-btn.gsl-control-btn-speed .gsl-control-dot { display: none !important; } .playback-rate-setting-panel { position: fixed; top: 0; left: 0; width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; background-color: rgba(0, 0, 0, 0.5); z-index: 999999; } .playback-rate-option-container { width: 240px; padding: 8px; display: flex; flex-direction: column; align-items: center; background-color: #FFFFFF; border-radius: 4px; user-select: none; } .playback-rate-option { width: 100%; margin-top: 2px; padding: 8px 0; color: #FFFFFF; background-color: #00AEEC; border-top: 1px solid #EEEEEE; border-radius: 4px; text-align: center; } .episode-container { display: flex; flex-direction: column; background-color: #f1f2f3; } .episode-container-header { display: flex; align-items: center; padding: 12px; padding-bottom: 10px; } .episode-container-header-count { margin-left: 4px; font-size: 0.8rem; font-family: monospace; color: #9499A0; } .episode-list { display: flex; flex-direction: column; padding: 12px; padding-top: 0; } .episode-list-item { display: flex; align-items: center; height: 36px; margin: 2px 0; padding: 2px 6px; } .episode-list-item.is-current-episode { background-color: #ffffff; color: #00AEEC; outline: 1px solid #7bdbfd; border-radius: 4px; } .episode-playing-gif { display: inline-block; width: 12px; height: 12px; margin-right: 5px; background-image: url('https://i0.hdslb.com/bfs/static/jinkela/playlist-video/asserts/playing.gif'); background-repeat: no-repeat; background-size: 12px 12px; background-position: center; } .episode-list-item-title { max-width: 250px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; line-height: 36px; font-size: 0.8rem; } .episode-list-item-duration { flex-grow: 1; text-align: right; font-size: 0.8rem; font-family: monospace; color: #9499A0; } #video-comment-module-wrapper { position: fixed; top: 0; left: 0; z-index: 2000; display: none; width: 100vw; height: 100vh; background-color: #fff; overflow-x: hidden; } .close-comment-module-btn { position: fixed; right: 20px; bottom: 20px; z-index: 2001; display: none; justify-content: center; align-items: center; width: 40px; height: 40px; color: #fff; border-radius: 100%; background-color: #00AEEC; } .open-comment-module-btn { display: flex; justify-content: center; align-items: center; margin: 0 12px 20px 12px; height: 40px; color: #fff; border-radius: 4px; background-color: #00AEEC; } `; document.head.appendChild(videoPageCSS); // space page const spacePageCSS = document.createElement('style'); spacePageCSS.textContent = ` .m-space-info { margin-top: 0 !important; } .bili-dyn-item { border-bottom: 1px solid #e7e7e7; } .video-item-space { box-sizing: border-box; margin-right: 3.2vmin; padding: 2.4vmin 0; height: 24.26667vmin; position: relative; display: block; border-bottom: 1px solid #ddd; } .video-item-space .cover { float: left; width: 31.2vmin; height: 19.46667vmin; position: relative; border-radius: 1.06667vmin; overflow: hidden; } .video-item-space .cover .duration { padding: 0 0.53333vmin; position: absolute; right: 1.06667vmin; bottom: 1.06667vmin; border-radius: 0.53333vmin; background: rgba(0,0,0,.5); font-size: 3.2vmin; color: #fff; } .video-item-space .info { margin-left: 34.4vmin; height: 19.46667vmin; position: relative; } .video-item-space .info .title { max-height: 9.06667vmin; font-size: 3.73333vmin; color: #212121; line-height: 4.53333vmin; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } .video-item-space .info .state { display: flex; align-items: center; position: absolute; bottom: 0; left: 0; right: 0; font-size: 2.66667vmin; color: #999; line-height: 4.53333vmin; height: 4.53333vmin; } .video-item-space .info .state .view, .video-item-space .info .state .danmaku { display: flex; align-items: center; } .video-item-space .info .state .danmaku { margin-left: 7.73333vmin; } .video-item-space .info .state .icon { margin-right: 1.06667vmin; } `; document.head.appendChild(spacePageCSS); // opus page const opusPageCSS = document.createElement('style'); opusPageCSS.textContent = ` .show-read-text { max-height: initial !important; } `; document.head.appendChild(opusPageCSS); // topic detail page const topicDetailPageCSS = document.createElement('style'); topicDetailPageCSS.textContent = ` .topic-detail-container { top: 0 !important; } `; document.head.appendChild(topicDetailPageCSS); } async function modifyNavBar() { const timer = setInterval(() => { const navBarElement = document.querySelector('.m-navbar'); if (navBarElement) { const parentElement = navBarElement.parentElement; if (parentElement.tagName === 'M-OPEN-APP') { parentElement.insertAdjacentElement('beforebegin', navBarElement); parentElement.remove(); } navBarElement.__vue__.$destroy(); navBarElement.innerHTML = ` <a class="nav-logo" href="/"><img src="https://i1.hdslb.com/bfs/static/jinkela/long/mstation/logo-bilibili-pink.png" /></a> <a class="nav-search" href="/search"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill="#CCCCCC" d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path></svg> </a> `; clearInterval(timer); } }, 100); } async function modifyHomePage() { // modify video card setInterval(() => { document.querySelectorAll('.card-box .v-card:not(.modified)').forEach(card => { // blacklist check const cardTitle = card.querySelector('.v-card__title'); if (blacklist.some(keyword => cardTitle.textContent.includes(keyword))) { card.remove(); return; } // rewrite behavior when video card being clicked if (card.__vue__?.bvid && card.__vue__?.$destroy) { const bvid = card.__vue__.bvid; card.onclick = () => window.location.href = `https://m.bilibili.com/video/${bvid}`; card.__vue__.$destroy(); card.querySelector('.sleepy')?.classList.remove('sleepy'); card.classList.add('modified'); } }); }, 100); } async function modifyVideoPage() { // show hidden video player const videoShare = await new Promise(resolve => { const timer = setInterval(() => { const videoShare = document.querySelector('.video-share'); if (videoShare) { videoShare.style.display = 'block'; videoShare.style.position = 'relative'; clearInterval(timer); resolve(videoShare); } }, 100); }); // add loading mask const loadingMask = document.createElement('div'); loadingMask.classList.add('video-share-loading-mask'); loadingMask.innerHTML = '<span class="video-share-loading-mask-circle"></span>'; videoShare.appendChild(loadingMask); // show loading mask when video share being clicked, but only once const videoShareOnClickHandler = () => { videoShare.removeEventListener('click', videoShareOnClickHandler); loadingMask.style.display = 'flex'; // hide the loading mask after the video start playing const timer = setInterval(() => { const progressBar = videoShare.querySelector('.gsl-ui-progress-bar'); if (progressBar && progressBar.style.width && progressBar.style.width !== '0%') { clearInterval(timer); loadingMask.style.display = 'none'; document.querySelector('.gsl-poster')?.remove(); } }, 50); } videoShare.addEventListener('click', videoShareOnClickHandler); // get video info const videoID = window.location.pathname.replace('/video/', ''); let param; if (videoID.startsWith('av')) param = `aid=${videoID.replace('av', '')}`; if (videoID.startsWith('BV')) param = `bvid=${videoID}`; const videoInfo = await fetch(`https://api.bilibili.com/x/web-interface/view?${param}`).then(res => res.json()).then(json => json.data); // add info const infoContainer = document.createElement('div'); infoContainer.classList.add('video-info'); infoContainer.innerHTML = ` <div class="video-info-title">${videoInfo.title}</div> <a class="video-info-author" href="https://m.bilibili.com/space/${videoInfo.owner.mid}"> <img class="video-info-author-avatar" src="${videoInfo.owner.face}"> <span class="video-info-author-name">${videoInfo.owner.name}</span> </a> <div class="video-info-desc" ${videoInfo.desc ? 'style="margin-top: 16px;"' : ''}>${videoInfo.desc.replaceAll('\n', '<br>').replaceAll(/BV[1-9A-HJ-NP-Za-km-z]{10}|av\d+/g, (match) => `<a style="color: #00AEEC" href="https://m.bilibili.com/video/${match}">${match}</a>`)}</div> `; document.querySelector('.video-share').insertAdjacentElement('afterend', infoContainer); // add comment module wrapper const commentModuleWrapper = document.createElement('div'); commentModuleWrapper.id = 'video-comment-module-wrapper'; document.body.appendChild(commentModuleWrapper); MobileCommentModule.init(commentModuleWrapper); // add button to close comment module const closeCommentModuleBtn = document.createElement('span'); closeCommentModuleBtn.classList.add('close-comment-module-btn'); closeCommentModuleBtn.textContent = '×'; closeCommentModuleBtn.onclick = function () { // trigger 'popstate' event window.history.back(); } document.body.appendChild(closeCommentModuleBtn); // add button to open comment module const openCommentModuleBtn = document.createElement('div'); openCommentModuleBtn.classList.add('open-comment-module-btn'); openCommentModuleBtn.textContent = '查看评论'; openCommentModuleBtn.onclick = function () { commentModuleWrapper.style.display = 'block'; closeCommentModuleBtn.style.display = 'flex'; document.body.style.overflow = 'hidden'; // push state in history window.history.pushState({}, ''); // close comment module when 'popstate' event triggered const popStateHandler = () => { commentModuleWrapper.style.display = 'none'; closeCommentModuleBtn.style.display = 'none'; document.body.style.overflow = 'initial'; document.querySelectorAll('.reply-item .preview-image-container').forEach(item => item.viewer?.hide(true)); window.removeEventListener('popstate', popStateHandler); } window.addEventListener('popstate', popStateHandler); } infoContainer.insertAdjacentElement('afterend', openCommentModuleBtn); // add episodes const partNum = parseInt((new URLSearchParams(window.location.search)).get('p') || '1'); const episodeContainer = document.createElement('div'); episodeContainer.classList.add('episode-container'); if (videoInfo.pages.length > 1) { episodeContainer.innerHTML = ` <div class="episode-container-header"> <span>视频选集</span> <span class="episode-container-header-count">(${partNum}/${videoInfo.pages.length})</span> </div> <div class="episode-list"> ${ videoInfo.pages.map((page, index) => { const isCurrentEpisode = partNum === index + 1; const second = page.duration % 60; const minute = (page.duration - second) / 60 % 60; const hour = Math.floor(page.duration / 3600); const formattedDuration = `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}:${String(second).padStart(2, '0')}`; return ` <a class="episode-list-item ${isCurrentEpisode ? 'is-current-episode' : ''}" ${isCurrentEpisode ? '' : `href="${window.location.pathname}?p=${index + 1}"`}> ${isCurrentEpisode ? '<span class="episode-playing-gif"></span>' : ''} <span class="episode-list-item-title">${page.part}</span> <span class="episode-list-item-duration">${formattedDuration}</span> </a> `; }).join('') } </div> `; } openCommentModuleBtn.insertAdjacentElement('afterend', episodeContainer); // move .bottom-tab to where it should be, usually happens when page open by b23.tv short url const bottomTab = document.querySelector('.video-share > .bottom-tab'); if (bottomTab) episodeContainer.insertAdjacentElement('afterend', bottomTab); // modify video card setInterval(() => { // move the video card out of <m-open-app> document.querySelectorAll('.card-box > m-open-app').forEach(item => { const href = item.getAttribute('universallink').replace('.html?', ''); item.outerHTML = item.querySelector('.card').outerHTML.replace('class="card"', `class="card" data-href="${href}"`).replaceAll('sleepy', ''); }); // setup click event document.querySelectorAll('.card-box > .card:not(.modified)').forEach(item => { // blacklist check const cardTitle = item.querySelector('.title'); if (blacklist.some(keyword => cardTitle.textContent.includes(keyword))) { item.remove(); return; } item.classList.add('modified'); item.onclick = () => window.location.href = item.dataset.href; }); }, 100); // modify playback rate button const timer4PlaybackRateBtn = setInterval(() => { const playbackRateBtn = document.querySelector('.gsl-control .gsl-control-btn-speed'); if (playbackRateBtn) { playbackRateBtn.onclick = () => { const maskElement = document.createElement('div'); maskElement.classList.add('playback-rate-setting-panel'); maskElement.innerHTML = ` <div class="playback-rate-option-container"> <span style="margin-bottom: 6px; padding: 6px 0;">播放倍速</span> <span class="playback-rate-option" data-rate="5">5.0x</span> <span class="playback-rate-option" data-rate="3">3.0x</span> <span class="playback-rate-option" data-rate="2">2.0x</span> <span class="playback-rate-option" data-rate="1.5">1.5x</span> <span class="playback-rate-option" data-rate="1">1.0x</span> <span class="playback-rate-option" data-rate="0.5">0.5x</span> </div> `; maskElement .querySelectorAll('.playback-rate-option') .forEach(optionElement => optionElement.addEventListener('click', function() { const videoElement = document.querySelector('#bilibiliPlayer video'); if (videoElement) videoElement.playbackRate = parseFloat(this.dataset.rate); })); maskElement.onclick = () => maskElement.remove(); (document.querySelector('#bilibiliPlayer .gsl-area.gsl-wide') || document.body).appendChild(maskElement); } clearInterval(timer4PlaybackRateBtn); } }, 100); // modify fullscreen button const timer4FullscreenBtn = setInterval(() => { const fullscreenBtn = document.querySelector('.gsl-btn-fullscreen'); if (fullscreenBtn) { // pre-click, whick needs 2 clicks to enter fullscreen naturally fullscreenBtn.click(); clearInterval(timer4FullscreenBtn); } }, 100); // modify ending panel of video const timer4EndingPanel = setInterval(async () => { const endingPanel = document.querySelector('.gsl-end.gsl-show .gsl-ending-panel-video'); if (endingPanel) { clearInterval(timer4EndingPanel); // clean click events endingPanel.innerHTML = ` <div class="gsl-ending-panel-video"> <div class="gsl-ending-panel-pic"> <img /> </div> <div class="gsl-ending-panel-content"> <div class="gsl-ending-panel-title"></div> <div class="gsl-ending-panel-button">点击打开</div> </div> </div> `; // get related video data const relatedVideoData = await fetch(`https://api.bilibili.com/x/web-interface/archive/related?bvid=${videoInfo.bvid}`).then(res => res.json()).then(json => json.data); // start showing let currentIndex; const currentVideoCover = endingPanel.querySelector('.gsl-ending-panel-pic img'); const currentVideoTitle = endingPanel.querySelector('.gsl-ending-panel-title'); const showRelatedVideo = () => { currentIndex = Math.floor(Math.random() * relatedVideoData.length); currentVideoCover.src = relatedVideoData[currentIndex].pic + '@460w_280h.webp'; currentVideoTitle.textContent = relatedVideoData[currentIndex].title; } showRelatedVideo(); setInterval(showRelatedVideo, 5 * 1000); // setup click event endingPanel.onclick = () => window.location.href = `https://m.bilibili.com/video/${relatedVideoData[currentIndex].bvid}`; } }, 100); // modify charge video page const timer4ChargeMask = setInterval(() => { const mask = document.querySelector('.m-video-player m-open-app.charge-mask'); if (mask) { mask.outerHTML = mask.outerHTML.replace('<m-open-app', '<div').replace('</m-open-app>', '</div>'); } }, 100); setTimeout(() => clearInterval(timer4ChargeMask), 3 * 1000); } async function modifySearchPage() { // modify cancel button const timer4CancelBtn = setInterval(() => { const cancelBtn = document.querySelector('.m-search-search-bar .cancel'); if (cancelBtn) { cancelBtn.outerHTML = cancelBtn.outerHTML.replace('class="cancel"', 'class="cancel" href="/"'); clearInterval(timer4CancelBtn); } }, 100); // modify video card setInterval(() => { document.querySelectorAll('.card-box .v-card-single:not(.vue-destroyed)').forEach(card => { // blacklist check const cardTitle = card.querySelector('.info .title'); const cardAuthor = card.querySelector('.info .author'); if (blacklist.some(keyword => cardTitle.textContent.includes(keyword) || cardAuthor.textContent.includes(keyword))) { card.remove(); return; } const aid = card.dataset.aid; // remove card which leading to live streaming if (aid === '0') { card.remove(); return; } // cancel default actions card.classList.add('vue-destroyed'); card.__vue__.$destroy(); // setup click event card.onclick = () => window.location.href = `https://m.bilibili.com/video/av${aid}`; // show covers card.querySelector('.sleepy')?.classList.remove('sleepy'); }); }, 100); // modify user card setInterval(() => { document.querySelectorAll('.card-box a.m-search-user-item:not(.vue-destroyed)').forEach(card => { card.classList.add('vue-destroyed'); card.__vue__.$destroy(); card.href = card.href.replace('?from=search', ''); card.querySelector('.sleepy')?.classList.remove('sleepy'); }); }, 100); } async function modifySpacePage() { // setup click event on user avatar if live streaming const timer4LiveStreaming = setInterval(() => { const face = document.querySelector('.m-space-info .info-main .face:not(.modified):has(.living-wrapper)'); const liveRoomID = window.__INITIAL_STATE__?.space?.info?.live_room?.roomid; if (face && liveRoomID) { face.classList.add('modified'); face.onclick = () => window.location.href = `https://live.bilibili.com/${liveRoomID}`; } }, 100); setTimeout(() => clearInterval(timer4LiveStreaming), 3 * 1000); // deactivate follow button const timer4FollowBtn = setInterval(() => { const followBtn = document.querySelector('.m-space-info .follow-btn'); if (followBtn) { followBtn.__vue__.$destroy(); clearInterval(timer4FollowBtn); } }, 100); // modify dynamic items setInterval(() => { document.querySelectorAll('.dynamic-list .list-scroll-content-wrap > m-open-app').forEach(item => { const dynItem = item.querySelector('.bili-dyn-item'); dynItem.onclick = () => window.location.href = item.getAttribute('universallink'); item.insertAdjacentElement('beforebegin', dynItem); item.remove(); }); }, 100); // modify archive list const timer4ArchiveList = setInterval(async () => { const archiveList = document.querySelector('.archive-list'); if (archiveList) { clearInterval(timer4ArchiveList); // get user id const mid = window.location.pathname.replace('/space/', ''); const getPaginationData = async (pn) => { const params = { mid, pn, ps: 50, order: 'senddate', wts: Math.floor(Date.now() / 1000) }; return fetch(`https://api.bilibili.com/x/space/wbi/arc/search?${await getWbiQueryString(params)}`, { credentials: 'include' }).then(res => res.json()).then(json => json.data.list?.vlist || []); }; const getVideoItem = (videoData) => { return ` <a href="/video/${videoData.bvid}" class="video-item-space"> <div class="cover"> <div class="bfs-img-wrap"> <div class="bfs-img b-img"> <img class="b-img__inner" src="${videoData.pic}@468w_292h_1c.webp" alt="${videoData.title}"> </div> </div> <span class="duration">${videoData.length}</span> </div> <div class="info"> <h3 class="title">${videoData.title}</h3> <div class="state"> <span class="view"> <svg class="icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16" width="16" height="16" style="width: 16px; height: 16px;"><path d="M8 3.3320333333333334C6.321186666666667 3.3320333333333334 4.855333333333333 3.4174399999999996 3.820593333333333 3.5013466666666666C3.1014733333333333 3.5596599999999996 2.5440733333333334 4.109013333333333 2.48 4.821693333333333C2.4040466666666664 5.666533333333334 2.333333333333333 6.780666666666666 2.333333333333333 7.998666666666666C2.333333333333333 9.216733333333334 2.4040466666666664 10.330866666666665 2.48 11.175699999999999C2.5440733333333334 11.888366666666666 3.1014733333333333 12.437733333333334 3.820593333333333 12.496066666666666C4.855333333333333 12.579933333333333 6.321186666666667 12.665333333333333 8 12.665333333333333C9.678999999999998 12.665333333333333 11.144933333333334 12.579933333333333 12.179733333333333 12.496033333333333C12.898733333333332 12.4377 13.456 11.888533333333331 13.520066666666667 11.176033333333333C13.595999999999998 10.331533333333333 13.666666666666666 9.217633333333332 13.666666666666666 7.998666666666666C13.666666666666666 6.779766666666667 13.595999999999998 5.665846666666667 13.520066666666667 4.821366666666666C13.456 4.108866666666666 12.898733333333332 3.55968 12.179733333333333 3.5013666666666663C11.144933333333334 3.417453333333333 9.678999999999998 3.3320333333333334 8 3.3320333333333334zM3.7397666666666667 2.50462C4.794879999999999 2.41906 6.288386666666666 2.3320333333333334 8 2.3320333333333334C9.7118 2.3320333333333334 11.2054 2.4190733333333334 12.260533333333331 2.5046399999999998C13.458733333333331 2.6018133333333333 14.407866666666665 3.5285199999999994 14.516066666666667 4.73182C14.593933333333332 5.597933333333334 14.666666666666666 6.7427 14.666666666666666 7.998666666666666C14.666666666666666 9.2547 14.593933333333332 10.399466666666665 14.516066666666667 11.2656C14.407866666666665 12.468866666666665 13.458733333333331 13.395566666666667 12.260533333333331 13.492766666666665C11.2054 13.578333333333333 9.7118 13.665333333333333 8 13.665333333333333C6.288386666666666 13.665333333333333 4.794879999999999 13.578333333333333 3.7397666666666667 13.492799999999999C2.541373333333333 13.395599999999998 1.5922066666666668 12.468633333333333 1.4840200000000001 11.265266666666665C1.4061199999999998 10.3988 1.3333333333333333 9.253866666666667 1.3333333333333333 7.998666666666666C1.3333333333333333 6.743533333333333 1.4061199999999998 5.598579999999999 1.4840200000000001 4.732153333333333C1.5922066666666668 3.5287466666666667 2.541373333333333 2.601793333333333 3.7397666666666667 2.50462z" fill="currentColor"></path><path d="M9.8092 7.3125C10.338433333333333 7.618066666666666 10.338433333333333 8.382 9.809166666666666 8.687533333333333L7.690799999999999 9.910599999999999C7.161566666666666 10.216133333333332 6.5 9.8342 6.500006666666666 9.223066666666666L6.500006666666666 6.776999999999999C6.500006666666666 6.165873333333334 7.161566666666666 5.783913333333333 7.690799999999999 6.089479999999999L9.8092 7.3125z" fill="currentColor"></path></svg> <span>${videoData.play < 10000 ? videoData.play : (parseInt(videoData.play) / 10000).toFixed(1) + '万'}</span> </span> <span class="danmaku"> <svg class="icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 16 16" width="16" height="16" style="width: 16px; height: 16px;"><path d="M8 3.3320333333333334C6.321186666666667 3.3320333333333334 4.855333333333333 3.4174399999999996 3.820593333333333 3.5013466666666666C3.1014733333333333 3.5596599999999996 2.5440733333333334 4.109013333333333 2.48 4.821693333333333C2.4040466666666664 5.666533333333334 2.333333333333333 6.780666666666666 2.333333333333333 7.998666666666666C2.333333333333333 9.216733333333334 2.4040466666666664 10.330866666666665 2.48 11.175699999999999C2.5440733333333334 11.888366666666666 3.1014733333333333 12.437733333333334 3.820593333333333 12.496066666666666C4.855333333333333 12.579933333333333 6.321186666666667 12.665333333333333 8 12.665333333333333C9.678999999999998 12.665333333333333 11.144933333333334 12.579933333333333 12.179733333333333 12.496033333333333C12.898733333333332 12.4377 13.456 11.888533333333331 13.520066666666667 11.176033333333333C13.595999999999998 10.331533333333333 13.666666666666666 9.217633333333332 13.666666666666666 7.998666666666666C13.666666666666666 6.779766666666667 13.595999999999998 5.665846666666667 13.520066666666667 4.821366666666666C13.456 4.108866666666666 12.898733333333332 3.55968 12.179733333333333 3.5013666666666663C11.144933333333334 3.417453333333333 9.678999999999998 3.3320333333333334 8 3.3320333333333334zM3.7397666666666667 2.50462C4.794879999999999 2.41906 6.288386666666666 2.3320333333333334 8 2.3320333333333334C9.7118 2.3320333333333334 11.2054 2.4190733333333334 12.260533333333331 2.5046399999999998C13.458733333333331 2.6018133333333333 14.407866666666665 3.5285199999999994 14.516066666666667 4.73182C14.593933333333332 5.597933333333334 14.666666666666666 6.7427 14.666666666666666 7.998666666666666C14.666666666666666 9.2547 14.593933333333332 10.399466666666665 14.516066666666667 11.2656C14.407866666666665 12.468866666666665 13.458733333333331 13.395566666666667 12.260533333333331 13.492766666666665C11.2054 13.578333333333333 9.7118 13.665333333333333 8 13.665333333333333C6.288386666666666 13.665333333333333 4.794879999999999 13.578333333333333 3.7397666666666667 13.492799999999999C2.541373333333333 13.395599999999998 1.5922066666666668 12.468633333333333 1.4840200000000001 11.265266666666665C1.4061199999999998 10.3988 1.3333333333333333 9.253866666666667 1.3333333333333333 7.998666666666666C1.3333333333333333 6.743533333333333 1.4061199999999998 5.598579999999999 1.4840200000000001 4.732153333333333C1.5922066666666668 3.5287466666666667 2.541373333333333 2.601793333333333 3.7397666666666667 2.50462z" fill="currentColor"></path><path d="M10.583333333333332 7.166666666666666L6.583333333333333 7.166666666666666C6.307193333333332 7.166666666666666 6.083333333333333 6.942799999999999 6.083333333333333 6.666666666666666C6.083333333333333 6.390526666666666 6.307193333333332 6.166666666666666 6.583333333333333 6.166666666666666L10.583333333333332 6.166666666666666C10.859466666666666 6.166666666666666 11.083333333333332 6.390526666666666 11.083333333333332 6.666666666666666C11.083333333333332 6.942799999999999 10.859466666666666 7.166666666666666 10.583333333333332 7.166666666666666z" fill="currentColor"></path><path d="M11.583333333333332 9.833333333333332L7.583333333333333 9.833333333333332C7.3072 9.833333333333332 7.083333333333333 9.609466666666666 7.083333333333333 9.333333333333332C7.083333333333333 9.0572 7.3072 8.833333333333332 7.583333333333333 8.833333333333332L11.583333333333332 8.833333333333332C11.859466666666666 8.833333333333332 12.083333333333332 9.0572 12.083333333333332 9.333333333333332C12.083333333333332 9.609466666666666 11.859466666666666 9.833333333333332 11.583333333333332 9.833333333333332z" fill="currentColor"></path><path d="M5.25 6.666666666666666C5.25 6.942799999999999 5.02614 7.166666666666666 4.75 7.166666666666666L4.416666666666666 7.166666666666666C4.140526666666666 7.166666666666666 3.9166666666666665 6.942799999999999 3.9166666666666665 6.666666666666666C3.9166666666666665 6.390526666666666 4.140526666666666 6.166666666666666 4.416666666666666 6.166666666666666L4.75 6.166666666666666C5.02614 6.166666666666666 5.25 6.390526666666666 5.25 6.666666666666666z" fill="currentColor"></path><path d="M6.25 9.333333333333332C6.25 9.609466666666666 6.02614 9.833333333333332 5.75 9.833333333333332L5.416666666666666 9.833333333333332C5.140526666666666 9.833333333333332 4.916666666666666 9.609466666666666 4.916666666666666 9.333333333333332C4.916666666666666 9.0572 5.140526666666666 8.833333333333332 5.416666666666666 8.833333333333332L5.75 8.833333333333332C6.02614 8.833333333333332 6.25 9.0572 6.25 9.333333333333332z" fill="currentColor"></path></svg> <span>${videoData.video_review}</span> </span> </div> </div> </a> `; }; const addAnchor = (container) => { const anchorElement = document.createElement('div'); anchorElement.classList.add('anchor-for-loading'); anchorElement.style = `margin-right: 3.2vmin; padding: 10vmin 0; text-align: center; font-size: 0.8rem; color: #61666d;`; anchorElement.textContent = '正在加载...'; container.appendChild(anchorElement); let paginationCounter = 1; const ob = new IntersectionObserver(async (entries) => { if (!entries[0].isIntersecting) return; const newPaginationData = await getPaginationData(++paginationCounter); if (newPaginationData instanceof Array && newPaginationData.length === 0) { anchorElement.textContent = '所有投稿已加载完毕'; ob.disconnect(); return; } for (const videoData of newPaginationData) { anchorElement.insertAdjacentHTML('beforebegin', getVideoItem(videoData)); } }); ob.observe(anchorElement); }; // get first pagination data const firstPaginationData = await getPaginationData(1); // return if there are no video archives if (firstPaginationData instanceof Array && firstPaginationData.length === 0) return; // clear archive list, then add video item archiveList.innerHTML = ''; for (const videoData of firstPaginationData) { archiveList.insertAdjacentHTML('beforeend', getVideoItem(videoData)); } // add anchor to the bottom addAnchor(archiveList); } }, 100); } async function modifyDynamicPage() { // if <m-open-app> still exists 1 second after opening the page, reload the page const noMoreOpenAppPromise = new Promise(resolve => { setTimeout(() => { if (document.querySelector('m-open-app')) window.location.reload(); else resolve(); }, 1000); }); // get cleaned dynamic card const dynamicCard = await new Promise(resolve => { const timer = setInterval(() => { const dynamicCardWrapper = document.querySelector('m-open-app.card-wrap'); if (dynamicCardWrapper) { clearInterval(timer); const dynamicCard = dynamicCardWrapper.querySelector('.dyn-card'); dynamicCardWrapper.insertAdjacentElement('beforebegin', dynamicCard); dynamicCardWrapper.remove(); resolve(dynamicCard); } }, 100); }); // setup click event on author avatar and name const spaceURL = dynamicCard.querySelector('.dyn-header').dataset.url; dynamicCard.querySelector('.dyn-header .dyn-header__author__avatar').onclick = () => window.location.href = spaceURL; dynamicCard.querySelector('.dyn-header .dyn-header__author__name').onclick = () => window.location.href = spaceURL; // setup click event on topic(original or referenced) dynamicCard.querySelectorAll('.dyn-content .bili-dyn-topic').forEach(item => { item.onclick = () => window.location.href = item.dataset.url; }); // setup click event on archive(original or referenced) dynamicCard.querySelectorAll('.dyn-content .dyn-archive').forEach(item => { item.onclick = () => window.location.href = `https://m.bilibili.com/video/${item.dataset.oid}`; }); // setup click event on rich-text-topic dynamicCard.querySelectorAll('.dyn-content .bili-richtext .bili-rich-text-topic').forEach(item => { item.onclick = () => window.location.href = item.dataset.url; }); // setup click event on rich-text-at dynamicCard.querySelectorAll('.dyn-content .bili-richtext .bili-rich-text-module.at').forEach(item => { item.onclick = () => window.location.href = `https://m.bilibili.com/space/${item.dataset.oid}`; }); // setup click event on rich-text-link dynamicCard.querySelectorAll('.dyn-content .bili-richtext .bili-rich-text-link:not(.viewpic)').forEach(item => { item.onclick = () => window.location.href = item.dataset.url; }); // setup click event on rich-text-link for viewing image const viewPicElements = dynamicCard.querySelectorAll('.dyn-content .bili-richtext .bili-rich-text-link.viewpic'); if (viewPicElements.length > 0) { let code, dynamicDetail; const dynamicID = window.location.pathname.replace('/dynamic/', ''); const parseResult = JSON.parse(window.localStorage.getItem('dynamicDetail')); if (parseResult && parseResult.data.item.id_str === dynamicID) { code = parseResult.code; dynamicDetail = parseResult.data; } else { const fetchResult = await fetch(`https://api.bilibili.com/x/polymer/web-dynamic/v1/detail?id=${dynamicID}`).then(res => res.json()); code = fetchResult.code; dynamicDetail = fetchResult.data; if (code === 0) window.localStorage.setItem('dynamicDetail', JSON.stringify(fetchResult)); } if (code === 0) { const viewPicNodes = [].concat( dynamicDetail.item.modules?.module_dynamic?.desc?.rich_text_nodes?.filter(node => node.type === 'RICH_TEXT_NODE_TYPE_VIEW_PICTURE') || [], dynamicDetail.item.orig?.modules?.module_dynamic?.desc?.rich_text_nodes?.filter(node => node.type === 'RICH_TEXT_NODE_TYPE_VIEW_PICTURE') || [], ); viewPicElements.forEach((viewPicElement, index) => { viewPicElement.insertAdjacentHTML('beforeend', `<div style="display: none;">${viewPicNodes[index].pics.map(pic => `<img src=${pic.src} />`).join('')}</div>`); const viewerInstance = new Viewer(viewPicElement, { title: false, toolbar: false, tooltip: false, keyboard: false }); viewPicElement.onclick = () => viewerInstance.show(); }); } } // setup image viewer on pics-block dynamicCard.querySelectorAll('.dyn-content .bm-pics-block').forEach(item => { new Viewer(item, { title: false, toolbar: false, tooltip: false, keyboard: false, url: (image) => image.src.slice(0, image.src.lastIndexOf('@')) }); }); // setup click event on goods card dynamicCard.querySelectorAll('.dyn-content .dyn-goods .dyn-goods__card > [data-url]').forEach(item => { item.onclick = () => window.location.href = item.dataset.url; }); // setup click event on goods list item dynamicCard.querySelectorAll('.dyn-content .dyn-goods .dyn-goods__card .dyn-goods__list__item > img').forEach(item => { item.onclick = () => window.location.href = item.dataset.url; }); // setup click event on live card dynamicCard.querySelectorAll('.dyn-content .dyn-live__card').forEach(item => { item.onclick = () => window.location.href = item.dataset.url; }); // setup click event on additional common card dynamicCard.querySelectorAll('.dyn-content .dyn-add-common').forEach(item => { item.onclick = () => window.location.href = item.dataset.url; }); // setup click event on reference author const referenceAuthor = dynamicCard.querySelector('.dyn-content .reference .dyn-orig-author'); if (referenceAuthor) { referenceAuthor.querySelector('.dyn-orig-author__following').remove(); referenceAuthor.onclick = () => window.location.href = referenceAuthor.dataset.url; } // setup click event on reference article const referenceArticle = dynamicCard.querySelector('.dyn-content .reference .dyn-article'); if (referenceArticle) { referenceArticle.onclick = async () => { let code, dynamicDetail; const dynamicID = window.location.pathname.replace('/dynamic/', ''); const parseResult = JSON.parse(window.localStorage.getItem('dynamicDetail')); if (parseResult && parseResult.data.item.id_str === dynamicID) { code = parseResult.code; dynamicDetail = parseResult.data; } else { const fetchResult = await fetch(`https://api.bilibili.com/x/polymer/web-dynamic/v1/detail?id=${dynamicID}`).then(res => res.json()); code = fetchResult.code; dynamicDetail = fetchResult.data; if (code === 0) window.localStorage.setItem('dynamicDetail', JSON.stringify(fetchResult)); } if (code === 0) { const jump_url = dynamicDetail.item.orig?.modules?.module_dynamic?.major?.article?.jump_url; if (jump_url) window.location.href = jump_url; } } } // setup comment module const timer4CommentModule = setInterval(() => { const wrapper = document.querySelector('.m-dynamic > .v-switcher'); if (wrapper) { clearInterval(timer4CommentModule); wrapper.className = 'comment-module-wrapper'; wrapper.style = `background-color: #fff; overflow-x: hidden;`; wrapper.innerHTML = ''; noMoreOpenAppPromise.then(_ => MobileCommentModule.init(wrapper)); } }, 100); } async function modifyOpusPage() { // if <m-open-app> still exists 1 second after opening the page, reload the page const noMoreOpenAppPromise = new Promise(resolve => { setTimeout(() => { if (document.querySelector('m-open-app')) window.location.reload(); else resolve(); }, 1000); }); // get data of opus modules const opusModules = await new Promise(resolve => { const timer = setInterval(() => { const opusModules = window.__INITIAL_STATE__?.opus?.detail?.modules; if (opusModules instanceof Array && opusModules.length !== 0) { clearInterval(timer); resolve(opusModules); } }, 100); }); // remove opus content read more limit const timer4OpusReadMoreLimit = setInterval(() => { document.querySelectorAll('.opus-module-content.limit').forEach(item => item.classList.remove('limit')); document.querySelectorAll('.opus-read-more').forEach(item => item.remove()); }, 100); setTimeout(() => clearInterval(timer4OpusReadMoreLimit), 3 * 1000); // setup image viewer on top album document.querySelectorAll('.opus-module-top .opus-module-top__album').forEach(item => { let previousImageAmount = item.querySelectorAll('.v-swipe__item img').length; const viewerInstance = new Viewer(item, { title: false, toolbar: false, tooltip: false, keyboard: false, url: (image) => image.src.slice(0, image.src.lastIndexOf('@')) }); setInterval(() => { const currentImageAmount = item.querySelectorAll('.v-swipe__item img').length; if (currentImageAmount > previousImageAmount) { previousImageAmount = currentImageAmount; viewerInstance.update(); } }, 500); }); // get cleaned author avatar and name const wrappedAuthorAvatar = document.querySelector('m-open-app.opus-module-author__avatar'); const wrappedAuthorName = document.querySelector('m-open-app.opus-module-author__name'); wrappedAuthorAvatar.outerHTML = wrappedAuthorAvatar.outerHTML.replace('<m-open-app', '<div').replace('</m-open-app', '</div'); wrappedAuthorName.outerHTML = wrappedAuthorName.outerHTML.replace('<m-open-app', '<div').replace('</m-open-app', '</div'); const authorAvatar = document.querySelector('.opus-module-author__avatar'); authorAvatar.querySelector('.sleepy')?.classList.remove('sleepy'); const authorName = document.querySelector('.opus-module-author__name'); // setup click event on author avatar and name const authorData = opusModules.find(module => module.module_type === 'MODULE_TYPE_AUTHOR')?.module_author; authorAvatar.onclick = () => window.location.href = authorData.jump_url; authorName.onclick = () => window.location.href = authorData.jump_url; // clean and setup click event on topic const timer4Topic = setInterval(() => { const wrapper = document.querySelector('m-open-app.opus-module-topic'); if (wrapper) { wrapper.outerHTML = wrapper.outerHTML.replace('<m-open-app', '<span').replace('</m-open-app', '</span'); const jump_url = opusModules.find(module => module.module_type === 'MODULE_TYPE_TOPIC')?.module_topic?.jump_url; if (jump_url) document.querySelector('.opus-module-topic').onclick = () => window.location.href = jump_url; } }, 100); setTimeout(() => clearInterval(timer4Topic), 3 * 1000); // clean and setup click event on rich-text-at document.querySelectorAll('m-open-app > .opus-text-rich-hl.at').forEach(item => { const wrapper = item.parentElement; wrapper.insertAdjacentElement('beforebegin', item); wrapper.remove(); const rid = opusModules.find(module => module.module_type === 'MODULE_TYPE_CONTENT')?.module_content?.paragraphs.find(paragraph => paragraph.para_type === 1)?.text?.nodes.find(node => node.type === 'TEXT_NODE_TYPE_RICH' && node?.rich?.type === 'RICH_TEXT_NODE_TYPE_AT' && node?.rich?.text === item.textContent)?.rich?.rid; if (rid) item.onclick = () => window.location.href = `https://m.bilibili.com/space/${rid}`; }); // clean and setup click event on rich-text-topic document.querySelectorAll('m-open-app > .opus-text-rich-hl.topic').forEach((item, index) => { const wrapper = item.parentElement; wrapper.insertAdjacentElement('beforebegin', item); wrapper.remove(); const jump_url = opusModules.find(module => module.module_type === 'MODULE_TYPE_CONTENT')?.module_content?.paragraphs.find(paragraph => paragraph.para_type === 1)?.text?.nodes.filter(node => node.type === 'TEXT_NODE_TYPE_RICH' && node?.rich?.type === 'RICH_TEXT_NODE_TYPE_TOPIC').at(index)?.rich?.jump_url; if (jump_url) item.onclick = () => window.location.href = jump_url; }); // clean and setup click event on rich-text-link document.querySelectorAll('m-open-app > .opus-text-rich-hl.link').forEach((item, index) => { const wrapper = item.parentElement; wrapper.insertAdjacentElement('beforebegin', item); wrapper.remove(); const jump_url = opusModules.find(module => module.module_type === 'MODULE_TYPE_CONTENT')?.module_content?.paragraphs.find(paragraph => paragraph.para_type === 1)?.text?.nodes.filter(node => node.type === 'TEXT_NODE_TYPE_RICH' && node?.rich?.type === 'RICH_TEXT_NODE_TYPE_WEB').at(index)?.rich?.jump_url; if (jump_url) item.onclick = () => window.location.href = jump_url; }); // clean and setup click event on rich-text-goods document.querySelectorAll('m-open-app > .opus-text-rich-hl.goods').forEach((item, index) => { const wrapper = item.parentElement; wrapper.insertAdjacentElement('beforebegin', item); wrapper.remove(); const jump_url = opusModules.find(module => module.module_type === 'MODULE_TYPE_CONTENT')?.module_content?.paragraphs.find(paragraph => paragraph.para_type === 1)?.text?.nodes.filter(node => node.type === 'TEXT_NODE_TYPE_RICH' && node?.rich?.type === 'RICH_TEXT_NODE_TYPE_GOODS').at(index)?.rich?.jump_url; if (jump_url) item.onclick = () => window.location.href = jump_url; }); // clean rich-text-lottery document.querySelectorAll('m-open-app > .opus-text-rich-hl.lottery').forEach((item, index) => { const wrapper = item.parentElement; wrapper.insertAdjacentElement('beforebegin', item); wrapper.remove(); }); // setup image viewer on pics-block document.querySelectorAll('.opus-module-content .bm-pics-block').forEach(item => { const wrapper = item.parentElement; if (wrapper.tagName === 'M-OPEN-APP') { wrapper.insertAdjacentElement('beforebegin', item); wrapper.remove(); } new Viewer(item, { title: false, toolbar: false, tooltip: false, keyboard: false, url: (image) => image.src.slice(0, image.src.lastIndexOf('@')) }); }); // clean reserve card and setup click event const timer4ReserveCard = setInterval(() => { const reserveCard = document.querySelector('m-open-app > .bm-link-card-reserve'); if (reserveCard) { const wrapper = reserveCard.parentElement; wrapper.insertAdjacentElement('beforebegin', reserveCard); wrapper.remove(); const jump_url = opusModules.find(module => module.module_type === 'MODULE_TYPE_CONTENT')?.module_content?.paragraphs.find(paragraph => paragraph.para_type === 6)?.link_card?.card?.reserve?.jump_url; if (jump_url) reserveCard.onclick = () => window.location.href = jump_url; } }, 100); setTimeout(() => clearInterval(timer4ReserveCard), 3 * 1000); // clean goods card and setup click event const timer4GoodsCard = setInterval(() => { const goodsCard = document.querySelector('m-open-app > .bm-link-card-goods'); if (goodsCard) { const wrapper = goodsCard.parentElement; wrapper.insertAdjacentElement('beforebegin', goodsCard); wrapper.remove(); goodsCard.querySelectorAll('.bm-link-card-goods__one[data-url]').forEach(item => { item.onclick = () => window.location.href = item.dataset.url; }); goodsCard.querySelectorAll('.bm-link-card-goods__list__item img').forEach(item => { item.onclick = () => window.location.href = item.dataset.url; }); } }, 100); setTimeout(() => clearInterval(timer4GoodsCard), 3 * 1000); // clean and setup click event on ugc card const timer4UgcCard = setInterval(() => { const ugcCard = document.querySelector('m-open-app > .bm-link-card-ugc'); if (ugcCard) { const wrapper = ugcCard.parentElement; wrapper.insertAdjacentElement('beforebegin', ugcCard); wrapper.remove(); const jump_url = opusModules.find(module => module.module_type === 'MODULE_TYPE_CONTENT')?.module_content?.paragraphs.find(paragraph => paragraph.para_type === 6)?.link_card?.card?.ugc?.jump_url; if (jump_url) ugcCard.onclick = () => window.location.href = jump_url; } }, 100); setTimeout(() => clearInterval(timer4UgcCard), 3 * 1000); // clean and setup click event on common card const timer4CommonCard = setInterval(() => { const commonCard = document.querySelector('m-open-app > .bm-link-card-common'); if (commonCard) { const wrapper = commonCard.parentElement; wrapper.insertAdjacentElement('beforebegin', commonCard); wrapper.remove(); commonCard.onclick = () => window.location.href = commonCard.dataset.url; } }, 100); setTimeout(() => clearInterval(timer4CommonCard), 3 * 1000); // setup comment module const timer4CommentModule = setInterval(() => { const wrapper = document.querySelector('.m-opus .v-switcher'); if (wrapper) { clearInterval(timer4CommentModule); wrapper.className = 'comment-module-wrapper'; wrapper.style = `background-color: #fff; overflow-x: hidden;`; wrapper.innerHTML = ''; noMoreOpenAppPromise.then(_ => MobileCommentModule.init(wrapper)); } }, 100); } async function modifyTopicDetailPage() { const timer4OpenApp = setInterval(() => { document.querySelectorAll('m-open-app').forEach(item => { item.outerHTML = item.outerHTML.replace('<m-open-app', '<div').replace('</m-open-app', '</div'); }); }, 100); setTimeout(() => clearInterval(timer4OpenApp), 3 * 1000); } async function getWbiQueryString(params) { // get origin key const { img_url, sub_url } = await fetch('https://api.bilibili.com/x/web-interface/nav').then(res => res.json()).then(json => json.data.wbi_img); const imgKey = img_url.slice(img_url.lastIndexOf('/') + 1, img_url.lastIndexOf('.')); const subKey = sub_url.slice(sub_url.lastIndexOf('/') + 1, sub_url.lastIndexOf('.')); const originKey = imgKey + subKey; // get mixin key const mixinKeyEncryptTable = [ 46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49, 33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40, 61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11, 36, 20, 34, 44, 52 ]; const mixinKey = mixinKeyEncryptTable.map(n => originKey[n]).join('').slice(0, 32); // generate basic query string const query = Object .keys(params) .sort() // sort properties by key .map(key => { const value = params[key].toString().replace(/[!'()*]/g, ''); // remove characters !'()* in value return `${encodeURIComponent(key)}=${encodeURIComponent(value)}` }) .join('&'); // calculate wbi sign const wbiSign = SparkMD5.hash(query + mixinKey); return query + '&w_rid=' + wbiSign; } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址