/** * @module rewrite * @description 重写页面框架模块,重写操作会完全刷新DOM,必须越快越好 * @license MIT */ (function () { const BLOD = window.BLOD; // 模块上下文,由主模块定义 const config = BLOD.config; // 脚本设置 const xhr = BLOD.xhr; // XMLHttpRequest const toast = BLOD.toast; // Toastr const debug = BLOD.debug; // 调试信息 /** * @class Rewrite * @description 重写页面 */ class Rewrite { constructor() { this.playerStyle = `#bofqi .player { width: 980px; height: 620px; display: block; } @media screen and (min-width:1400px) { #bofqi .player { width: 1160px; height: 720px } }`; this.playerStyleC = `#bofqi .player { width: 980px; height: 620px; display: block; } @media screen and (min-width:1400px) { #bofqi .player { width: 1294px; height: 792px } #__bofqi { min-height: 760px; } .bili-wrapper { width: 1294px; } .bgray-btn-wrap { margin-left: 647px !important; } .fixed-nav-m { margin-left: 657px; } .bili-wrapper { width: 1294px !important; } .primary-menu { width: 1294px !important; } } @media screen and (min-width:2800px) { #bofqi .player { width: 1934px; height: 1152px } #__bofqi { min-height: 1120px; } .bili-wrapper { width: 1934px; } .bgray-btn-wrap { margin-left: 967px !important; } .fixed-nav-m { margin-left: 977px; } .bili-wrapper { width: 1934px !important; } .primary-menu { width: 1934px !important; } }`; this.oldreply = `.bb-comment .comment-list .list-item .user-face img, .comment-bilibili-fold .comment-list .list-item .user-face img { width: 48px; height: 48px; border-radius: 50%; } .bb-comment .comment-list .list-item .user-face .pendant, .comment-bilibili-fold .comment-list .list-item .user-face .pendant { width: 86px; height: 86px; position: absolute; top: -19px; left: -19px; display: block; } .bb-comment .comment-list .list-item .user-face .pendant img, .comment-bilibili-fold .comment-list .list-item .user-face .pendant img { border: 0; border-radius: 0; width: 86px; height: 86px; }`; this.miniPlayer = `.bilibili-player .bilibili-player-area .bilibili-player-video-wrap.mini-player .bilibili-player-video-danmaku { top: 30px; height: 240px; } .bilibili-player .bilibili-player-area .bilibili-player-video-wrap.mini-player .bilibili-player-video-bas-danmaku { top: 30px; height: 240px; } .bilibili-player .bilibili-player-area .bilibili-player-video-wrap.mini-player .bilibili-player-video-adv-danmaku { top: 30px; height: 240px; }`; this.imroot = `.im-root,.im-root .im-list-box * { font-size:12px; line-height:42px; } .im-root .im-list-box { width:100%; overflow: visible; } .im-root .im-list-box .im-list { line-height:42px; height:42px; } .im-root .im-list-box .im-notify.im-number { height: 14px; line-height: 13px; border-radius: 10px; padding: 1px 3px; font-size: 12px; min-width: 20px; text-align: center; color: #fff; } .im-root .im-list-box .im-notify.im-number.im-center { top: 14px; left: 80px; } .im-root .im-list-box .im-notify.im-dot { top: 11px; right: -10px; width: 8px; height: 8px; border-radius: 100%; } .im-root .im-list-box .im-notify.im-dot.im-center { top: 16px; right: 20px; }`; this.iconLike = BLOD.GM.getResourceText("iconLike"); this.iconDislike = BLOD.GM.getResourceText("iconDislike"); if (config.rewrite.av && /\/video\/[AaBb][Vv]/.test(location.href)) this.av(); if (config.rewrite.bangumi && /\/bangumi\/play\/(ss|ep)/.test(location.href)) this.bangumi(); if (config.rewrite.watchlater && /\/watchlater\//.test(location.href)) this.watchlater(); if (config.rewrite.frame && /player\./.test(location.href)) this.blackboard(); if (/space\.bilibili\.com/.test(location.href)) this.space(); if (config.rewrite.home && BLOD.path[2] == 'www.bilibili.com' && (!BLOD.path[3] || (BLOD.path[3].startsWith('\?') || BLOD.path[3].startsWith('\#') || BLOD.path[3].startsWith('index.')))) this.index(); if (config.rewrite.rank && /\/v\/popular\//.test(location.href)) this.rank(); if (/live\.bilibili\.com/.test(location.href)) this.live(); if (/\/medialist\/play\//.test(location.href)) this.medialist(); if (BLOD.path[2] == "message.bilibili.com") BLOD.addCss(".container[data-v-6969394c] { height: calc(100vh - 42px) !important;} .container[data-v-1c9150a9] { height: calc(100vh - 42px) !important;}"); // 修复消息页样式 if (window.self == window.top && BLOD.path[2] == 'www.bilibili.com') document.domain = "bilibili.com"; // 处理子页面跨域 if (location.href.includes("message.bilibili.com/pages/nav/index_new_sync")) BLOD.addCss(this.imroot); // 修复顶栏消息框 if (location.href.includes("www.bilibili.com/account/history")) { // 隐藏历史记录搜索 if (config.reset.searchHistory) BLOD.joinNode(() => BLOD.removeElement("b-head-search", "class")); if (config.reset.history) { // 只显示视频历史 BLOD.xhrhook((xhr, args) => { if (args[1].includes('api.bilibili.com/x/web-interface/history/cursor') && args[1].includes("business")) { let obj = BLOD.urlObj(args[1]), max = obj.max || "", view_at = obj.view_at || ""; args[1] = BLOD.objUrl("//api.bilibili.com/x/web-interface/history/cursor", { max: max, view_at: view_at, type: "archive", ps: 20 }); } }) } } if (/dmid/.test(location.href) && /dm_progress/.test(location.href)) BLOD.joinSwitchVideo(() => this.loadByDmid()); // 处理弹幕跳转 if (config.rewrite.read && /\/read\/[Cc][Vv]/.test(location.href)) this.read(); } /** * av/BV * @returns {void} */ av() { try { if (/\/s\//.test(location.href)) location.replace(location.href.replace("s/video", "video")); // 重定向SEO页面 BLOD.path.name = true; // 重写指示,有些操作无需再重写页面生效 this.ml = BLOD.GM.getValue("medialist"); // 读取临时储存,检查是否medialist跳转而来 BLOD.GM.deleteValue("medialist"); // 清除临时储存 BLOD.importModule("initialstate"); // 准备__INITIAL_STATE__重构 if (config.reset.novideo || config.reset.forceFlv) BLOD.getVariable(window, "__playinfo__", undefined, [undefined]); // 清除__playinfo__缓存 BLOD.playerSetting(); // 还原旧版播放器设置 // 获取aid if (BLOD.path[4].toLowerCase().startsWith('bv')) BLOD.aid = BLOD.abv(BLOD.path[4].split("#")[0].split("?")[0]); // 若为BV,转为aid BLOD.aid = BLOD.aid || BLOD.path[4].match(/[0-9]+/)[0]; // 若为av,直接读取 this.page = xhr.false(BLOD.objUrl("https://api.bilibili.com/x/web-interface/view/detail", { aid: BLOD.aid })); // 获取__INITIAL_STATE__ BLOD.__INITIAL_STATE__ = BLOD.iniState.av(this.page); // 重构__INITIAL_STATE__ if (!BLOD.__INITIAL_STATE__) { // 尝试访问第三方缓存数据 this.page = xhr.false(BLOD.objUrl("https://www.biliplus.com/api/view", { id: BLOD.aid })); BLOD.__INITIAL_STATE__ = BLOD.iniState.avPlus(this.page); if (!config.reset.lostvideo) return toast.error("av/BV号可能无效!", "设置中启用【失效视频】将尝试访问第三方缓存数据"); } if (!BLOD.__INITIAL_STATE__) return toast.error("av/BV号可能无效!"); // 获取__INITIAL_STATE__失败 if (BLOD.__INITIAL_STATE__.videoData.redirect_url) return toast.warning("番剧重定向...", BLOD.__INITIAL_STATE__.videoData.redirect_url); // 页面重定向 if (BLOD.__INITIAL_STATE__.videoData.stein_guide_cid) return toast.warning("这似乎是个互动视频!", "抱歉!旧版播放器无法支持 ಥ_ಥ"); // 忽略互动视频 // 记录关键变量 BLOD.aid = BLOD.__INITIAL_STATE__.aid ? BLOD.__INITIAL_STATE__.aid : BLOD.aid; BLOD.tid = BLOD.__INITIAL_STATE__.videoData.tid ? BLOD.__INITIAL_STATE__.videoData.tid : BLOD.tid; window.__INITIAL_STATE__ = BLOD.__INITIAL_STATE__; // 写入旧版__INITIAL_STATE__ BLOD.write(this.oldScript(BLOD.GM.getResourceText("av"))); // 重写av页 document.title = BLOD.__INITIAL_STATE__.videoData.title + "_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili"; // 主动写入标签页标题 config.reset.playerStyle ? BLOD.addCss(this.playerStyleC) : BLOD.addCss(this.playerStyle); // 修正播放器样式 if (config.reset.oldreply) BLOD.addCss(this.oldreply); // 修正旧版评论样式 let n = BLOD.joinNode(() => { // 移除原失效顶栏 BLOD.removeElement("bili-header-m report-wrap-module", "class", false, 1, () => { BLOD.quitNode(n) }); }) this.fixVideoSeek(); // 修复评论跳转链接 this.videoSort(); // 修复分区数据 if (config.reset.like) this.setLike(); // 切P回调添加点赞功能 if (this.ml) this.setMediaList(); // 如果存在媒体缓存,构造媒体页 if (BLOD.staff && config.reset.uplist) this.uplist(); // 添加UP主列表 if (config.reset.commandDm) this.commandDm(); // 添加互动弹幕 BLOD.joinSwitchVideo(() => this.avdesc()); // 视频简介BV号转化 this.hookWebpackJsonp(); // hook原生代码以修复bug if (config.reset.electric) { // 跳过充电鸣谢 BLOD.jsonphook((xhr, jsonp) => { if (jsonp.url.includes("api.bilibili.com/x/web-interface/elec/show")) jsonp.url = BLOD.objUrl(jsonp.url.split("?")[0], Object.assign(BLOD.urlObj(jsonp.url), { aid: 1, mid: 1 })); }) } this.mediaControl(__INITIAL_STATE__.videoData.title, __INITIAL_STATE__.videoData.owner.name, (pid, playList) => playList[pid].part, () => [{ src: __INITIAL_STATE__.videoData.pic, sizes: "320x180" }], () => player.getPlaylistIndex()); } catch (e) { e = Array.isArray(e) ? e : [e]; toast.error("页面重写", ...e); } } /** * 重写Bangumi * @returns {void} */ bangumi() { try { BLOD.path.name = true; // 重写指示,有些操作无需再重写页面生效 BLOD.importModule("initialstate"); // 准备__INITIAL_STATE__重构 BLOD.playerSetting(); // 还原旧版播放器设置 BLOD.pgc = true; // Bangumi指示,一般用于视频链接获取区分 let data = (BLOD.uid && xhr.false(location.href).match(/last_ep_id\"\:[0-9]+/)) || []; // 尝试获取历史记录 let id = BLOD.path[5].startsWith('ep') ? location.href.match(/[0-9]+/)[0] : null; // 尝试获取epid id = id || (data[0] && data[0].split(":")[1]) || null; // 存在epid直接覆盖历史 try { // 尝试获取__INITIAL_STATE__,分ss/ep两种情况 if (BLOD.path[5].startsWith('ss')) { data = xhr.false(BLOD.objUrl("https://bangumi.bilibili.com/view/web_api/season", { season_id: location.href.match(/[0-9]+/)[0] })); } else if (BLOD.path[5].startsWith('ep')) { data = xhr.false(BLOD.objUrl("https://bangumi.bilibili.com/view/web_api/season", { ep_id: location.href.match(/[0-9]+/)[0] })); } BLOD.__INITIAL_STATE__ = BLOD.iniState.bangumi(data, id); // 重构__INITIAL_STATE__ } catch (e) { // 无法获取__INITIAL_STATE__,尝试泰区接口,需要区域代理 let thai = BLOD.GM.getValue("thaiLand") || "https://api.global.bilibili.com"; // 获取泰区代理 if (!config.reset.limit) throw e; // 未启用解除区域限制功能 try { // 尝试获取__INITIAL_STATE__,同样分ss/ep两种情况 if (BLOD.path[5].startsWith('ss')) { data = BLOD.xhr.false(BLOD.objUrl(`${thai}/intl/gateway/v2/ogv/view/app/season`, { season_id: location.href.match(/[0-9]+/)[0] })); } else if (BLOD.path[5].startsWith('ep')) { data = BLOD.xhr.false(BLOD.objUrl(`${thai}/intl/gateway/v2/ogv/view/app/season`, { ep_id: location.href.match(/[0-9]+/)[0] })); } BLOD.__INITIAL_STATE__ = BLOD.iniState.thaiBangumi(data, id); // 重构__INITIAL_STATE__ BLOD.limit = 1; // 区域限制标志 BLOD.thailand = true; // 泰区标志,用于解除限制类型区分 } catch (no) { throw e } } if (BLOD.__INITIAL_STATE__ && BLOD.__INITIAL_STATE__.epInfo && BLOD.__INITIAL_STATE__.epInfo.badge === "互动") return toast.warning("这似乎是个互动番剧!", "什么!番剧也能互动?", "可惜旧版播放器不支持 ಥ_ಥ"); // 忽略互动视频 if (!config.reset.bangumiCover && BLOD.__INITIAL_STATE__ && BLOD.__INITIAL_STATE__.epList && BLOD.__INITIAL_STATE__.epList[1]) { // Bangumi存在特殊背景,但为了显示分集,清除特殊背景 BLOD.__INITIAL_STATE__.special = false; BLOD.__INITIAL_STATE__.mediaInfo.bkg_cover = undefined; } window.__INITIAL_STATE__ = BLOD.__INITIAL_STATE__; // 写入旧版__INITIAL_STATE__ // 重写Bangumi页面,区分特殊背景页面 if (!BLOD.__INITIAL_STATE__.special) BLOD.write(this.oldScript(BLOD.GM.getResourceText("bangumi"))); else BLOD.write(this.oldScript(BLOD.GM.getResourceText("cinema"))); if (config.reset.oldreply) BLOD.addCss(this.oldreply); // 修正旧版评论样式 document.title = BLOD.__INITIAL_STATE__.mediaInfo.title + "_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili"; // 主动写入标题 if (BLOD.__INITIAL_STATE__ && config.reset.episodedata) BLOD.joinSwitchVideo(() => this.episodeData()); // 切P回调分集数据 let rid = BLOD.joinNode(() => { BLOD.removeElement("new-entry", "class", false, 0, () => BLOD.quitNode(rid)); }) BLOD.xhrhook((xhr, args) => { // 修复追番数据 if (args[1].includes('bangumi.bilibili.com/ext/web_api/season_count?')) { xhr.addEventListener('readystatechange', () => { if (xhr.readyState === 4) { try { let response = BLOD.jsonCheck(xhr.responseText); response.result.favorites = response.result.follow; Object.defineProperty(xhr, 'response', { writable: true }); Object.defineProperty(xhr, 'responseText', { writable: true }); xhr.response = xhr.responseText = JSON.stringify(response); } catch (e) { e = Array.isArray(e) ? e : [e]; debug.error("番剧追番信息", ...e) } } }); args[1] = args[1].replace('bangumi.bilibili.com/ext/web_api/season_count', 'api.bilibili.com/pgc/web/season/stat'); } // 修复片尾番剧推荐 if (args[1].includes('api.bilibili.com/pgc/web/recommend/related/recommend')) { xhr.addEventListener('readystatechange', () => { if (xhr.readyState === 4) { try { let response = BLOD.jsonCheck(xhr.responseText); if (response.result && response.result.season) response.result = response.result.season; Object.defineProperty(xhr, 'response', { writable: true }); Object.defineProperty(xhr, 'responseText', { writable: true }); xhr.response = xhr.responseText = JSON.stringify(response); } catch (e) { e = Array.isArray(e) ? e : [e]; toast.error("番剧推荐", ...e) } } }) } // 修复番剧推荐 if (args[1].includes('comment.bilibili.com/playtag')) { args[1] = "https://comment.bilibili.com/playtag,2-2?html5=1"; this.pgcRecommend(); } }) let epListMap = []; __INITIAL_STATE__.epList.forEach((v, i) => epListMap[v.cid] = i); this.mediaControl(__INITIAL_STATE__.mediaInfo.title, __INITIAL_STATE__.mediaInfo.jp_title, pid => __INITIAL_STATE__.epList[pid].index_title, pid => [{ src: __INITIAL_STATE__.epList[pid].cover, sizes: "960x600" }], () => epListMap[BLOD.cid]); Object.defineProperty(window, "pageno", { get: () => epListMap[BLOD.cid] + 1 }); } catch (e) { e = Array.isArray(e) ? e : [e]; toast.error("页面重写", ...e); } } /** * 稍后再看 * @returns {void} */ watchlater() { if (!BLOD.uid) return toast.warning("未登录!", "无法启用稍后再看"); // 忽略未登录用户 BLOD.path.name = true; // 重写指示,有些操作无需再重写页面生效 BLOD.playerSetting(); // 还原旧版播放器设置 BLOD.write(this.oldScript(BLOD.GM.getResourceText("watchlater"))); // 重写稍后再看 config.reset.playerStyle ? BLOD.addCss(this.playerStyleC) : BLOD.addCss(this.playerStyle); // 修正播放器样式 if (config.reset.oldreply) BLOD.addCss(this.oldreply); // 修正旧版评论样式 this.fixVideoSeek(); // 修复评论跳转链接 this.watchlaterSort(); // 修复分区数据 if (config.reset.like) this.setLike(); // 切P回调添加点赞功能 BLOD.addCss(this.miniPlayer); // 修正mini播放器大小 } /** * 嵌入播放器 * @returns {void} */ blackboard() { BLOD.path.name = true; // 重写指示,有些操作无需再重写页面生效 BLOD.playerSetting(); // 还原旧版播放器设置 BLOD.write(this.oldScript(BLOD.GM.getResourceText("player"))); } /** * 播单页面,失效。相关接口已404 */ playlist() { if (BLOD.path[4] == "video") { // playlist播放页面 BLOD.path.name = true; // 重写指示,有些操作无需再重写页面生效 BLOD.write(this.oldScript(BLOD.GM.getResourceText("playlist"))); toast.warning("播单页相关接口已失效!", "脚本也无法恢复 ಥ_ಥ"); } if (BLOD.path[4] == "detail") { // playlist详情页面 BLOD.path.name = true; // 重写指示,有些操作无需再重写页面生效 BLOD.__INITIAL_STATE__ = { mid: "", pid: "", plinfoData: {}, pllistData: {} } try { let page = BLOD.jsonCheck(xhr.false(BLOD.objUrl("https://api.bilibili.com/x/playlist/video/toview", { pid: BLOD.path[5].match(/[0-9]+/)[0] }))).data; BLOD.__INITIAL_STATE__.mid = page.mid; BLOD.__INITIAL_STATE__.pid = page.pid; BLOD.__INITIAL_STATE__.plinfoData = { attr: page.attr, count: page.count, cover: page.cover, ctime: page.ctime, description: page.description, favored: page.favored, id: page.id, is_favorite: page.is_favorite, mid: page.mid, mtime: page.mtime, owner: page.owner, pid: page.pid, stat: page.stat, state: page.state, type: page.type, }; BLOD.__INITIAL_STATE__.pllistData = page.list; } catch (e) { e = Array.isArray(e) ? e : [e]; debug.error("播单", ...e); BLOD.__INITIAL_STATE__ = JSON.parse(BLOD.getResourceText("playlistjson")); } window.__INITIAL_STATE__ = BLOD.__INITIAL_STATE__; BLOD.write(this.oldScript(BLOD.GM.getResourceText("playlistdetail"))); toast.warning("无法获取播单例表!", "这里使用的是一例备份数据以供参考"); } } /** * 媒体播放页 * @returns {void} */ medialist() { if (BLOD.path[5].startsWith("ml")) { this.ml = 1 * BLOD.path[5].match(/[0-9]+/)[0]; // 保存收藏号并调用av跳转 if (!config.rewrite.medialist) return; BLOD.GM.setValue("medialist", this.ml); this.setMediaList(this.ml); } // 新版稍后再看跳转到旧版稍后再看 if (BLOD.path[5].startsWith("watchlater") && config.rewrite.watchlater) location.replace("https://www.bilibili.com/watchlater/#/"); } /** * 个人主页 */ async space() { BLOD.mid = (BLOD.path[3] && BLOD.path[3].split("?")[0]) || BLOD.mid; // 修复番剧出差数据 BLOD.xhrhook((xhr, args) => { if (BLOD.mid == 11783021 && args[1].includes("api.bilibili.com/x/space/acc/info")) { xhr.addEventListener('readystatechange', () => { if (xhr.readyState === 4) { if (xhr.responseText && xhr.responseText.includes("-404")) { let response = { "code": 0, "data": { "birthday": "1980-01-01", "coins": 0, "face": "http://i2.hdslb.com/bfs/face/9f10323503739e676857f06f5e4f5eb323e9f3f2.jpg", "fans_badge": false, "is_followed": true, "jointime": 1436351229, "level": 6, "mid": "11783021", "moral": 0, "name": "哔哩哔哩番剧出差", "official": { "type": 1, "desc": "哔哩哔哩番剧出差 官方账号" }, "pendant": { "pid": 0, "name": "", "image": "", "expire": 0 }, "rank": "10000", "sex": "保密", "sign": "", "silence": 0, "sys_notice": {}, "theme": {}, "user_honour_info": { "colour": null, "mid": 0, "tags": null }, "vip": { "avatar_subscript": 1, "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png", "due_date": 1655740800000, "label": { "bg_color": "#FB7299", "bg_style": 1, "border_color": "", "label_theme": "annual_vip", "path": "", "text": "年度大会员", "text_color": "#FFFFFF" }, "nickname_color": "#FB7299", "role": 3, "status": 1, "theme_type": 0, "type": 2, "vip_pay_type": 1 } }, "message": "0", "ttl": 1 }; Object.defineProperty(xhr, 'response', { writable: true }); Object.defineProperty(xhr, 'responseText', { writable: true }); xhr.response = xhr.responseText = JSON.stringify(response); toast.warning("该用户被404,已使用缓存数据恢复访问!") } } }); } // 恢复相簿链接 if (args[1].includes("api.bilibili.com/x/dynamic/feed/draw/doc_list")) { xhr.addEventListener('readystatechange', () => { if (xhr.readyState === 4) { let response = JSON.parse(xhr.responseText); let data = response.data.items.reduce((s, d) => { s.push(d.doc_id); return s; }, []); setTimeout(() => { document.querySelectorAll(".album-card").forEach((d, i) => { d.firstChild.href = `//h.bilibili.com/${data[i]}`; d.children[1].href = `//h.bilibili.com/${data[i]}` }) }, 1000) } }); } }) if (BLOD.mid && config.reset.jointime) { try { let data = await xhr.GM(BLOD.objUrl("https://account.bilibili.com/api/member/getCardByMid", { "mid": BLOD.mid })); data = BLOD.jsonCheck(data); // 格式化时间戳,不是13位,主动补位 let jointime = BLOD.timeFormat(data.card.regtime * 1000, 1); if (BLOD.big) toast(data.card.name + " mid:" + BLOD.mid, "注册时间:" + jointime, "生日:" + data.card.birthday); debug.log("注册时间", data.card.name, jointime); document.addEventListener("DOMNodeInserted", (msg) => { let node = document.querySelector(".user-info-title"); if (node) { if (document.querySelector(".info-jointime")) return; else { let span = BLOD.addElement("span", { class: "info-jointime" }, node); span.innerText = jointime; } } }); } catch (e) { e = Array.isArray(e) ? e : [e]; toast.error("注册时间", ...e); } } if (config.reset.lostvideo) this.lostVideo(); } /** * 主页 */ index() { BLOD.path.name = true; // 重写指示,有些操作无需再重写页面生效 BLOD.importModule("initialstate"); // 准备__INITIAL_STATE__重构 // 获取__INITIAL_STATE__ if (!window.__INITIAL_STATE__ && !window.__INITIAL_DATA__) { let page = xhr.false(location.href); BLOD.__INITIAL_STATE__ = page.includes("__INITIAL_STATE__=") ? page.match(/INITIAL_STATE__=.+?\;\(function/)[0].replace(/INITIAL_STATE__=/, "").replace(/;\(function/, "") : ""; BLOD.__INITIAL_DATA__ = page.includes("__INITIAL_DATA__=") ? page.match(/INITIAL_DATA__=.+?<\/script>/)[0].replace(/INITIAL_DATA__=/, "").replace(/<\/script>/, "") : ""; } else { BLOD.__INITIAL_STATE__ = JSON.stringify(window.__INITIAL_STATE__); BLOD.__INITIAL_DATA__ = JSON.stringify(window.__INITIAL_DATA__); } BLOD.__INITIAL_STATE__ && (BLOD.__INITIAL_STATE__ = BLOD.iniState.index(BLOD.__INITIAL_STATE__)); // 重构__INITIAL_STATE__ BLOD.__INITIAL_DATA__ && (BLOD.__INITIAL_STATE__ = BLOD.iniState.indexnew(BLOD.__INITIAL_DATA__)); // 移除广告 if (BLOD.config.reset.adloc) { for (let key in BLOD.__INITIAL_STATE__.locsData) { if (Array.isArray(BLOD.__INITIAL_STATE__.locsData[key])) { BLOD.__INITIAL_STATE__.locsData[key] = BLOD.__INITIAL_STATE__.locsData[key].filter(d => { return d.is_ad ? (debug.debug("移除广告", key, d) && false) : true; }) } } } window.__INITIAL_STATE__ = BLOD.__INITIAL_STATE__; //写入旧版__INITIAL_STATE__ BLOD.write(BLOD.GM.getResourceText("index")); // 重写主页 let rid = BLOD.joinNode(() => { // 移除无效节点 BLOD.removeElement("ver", "class"); BLOD.removeElement("fixed_app_download", "id", false, 0, () => BLOD.quitNode(rid)); }) BLOD.xhrhook((xhr, args) => { // 修复直播推荐 if (args[1].includes('api.live.bilibili.com/room/v1/RoomRecommend/biliIndexRec')) { xhr.addEventListener('readystatechange', () => { if (xhr.readyState === 4) { try { let response = xhr.responseText.replace(/preview_banner_list/, "preview").replace(/ranking_list/, "ranking").replace(/recommend_room_list/, "recommend"); response = JSON.parse(response); response.data.text_link = { text: "233秒居然能做这些!", link: "//vc.bilibili.com" }; if (response.data.recommend) { for (let i = 0; i < response.data.recommend.length; i++) { response.data.recommend[i].pic = response.data.recommend[i].cover; response.data.recommend[i].link = "//live.bilibili.com" + response.data.recommend[i].link; } } if (response.data.preview) for (let i = 0; i < response.data.preview.length; i++) response.data.preview[i].url = response.data.preview[i].link; Object.defineProperty(xhr, 'response', { writable: true }); Object.defineProperty(xhr, 'responseText', { writable: true }); xhr.response = xhr.responseText = JSON.stringify(response); } catch (e) { e = Array.isArray(e) ? e : [e]; debug.error("获取直播数据推荐及排行失败!", ...e); } } }) args[1] = args[1].includes("List") ? args[1].replace('api.live.bilibili.com/room/v1/RoomRecommend/biliIndexRecList', 'api.live.bilibili.com/xlive/web-interface/v1/webMain/getList?platform=web') : arg[1].replace('api.live.bilibili.com/room/v1/RoomRecommend/biliIndexRecMore', 'api.live.bilibili.com/xlive/web-interface/v1/webMain/getMoreRecList?platform=web'); } }) BLOD.jsonphook((xhr, jsonp) => { // 广告区转资讯区 if (jsonp.url.includes("region") && jsonp.url.includes("rid=165")) jsonp.url = jsonp.url.replace("rid=165", "rid=202"); // 用户热点最新投稿修复资讯区最新投稿 if (jsonp.url.includes("newlist") && jsonp.url.includes("rid=165")) jsonp.url = jsonp.url.replace("rid=165", "rid=203"); // 取消原创排行榜 if (jsonp.url.includes("region") && jsonp.url.includes("original=1")) jsonp.url = jsonp.url.replace("original=1", "original=0"); // 修复置顶推荐 if (jsonp.url.includes("api.bilibili.com/x/web-interface/ranking/index")) jsonp.url = jsonp.url.replace("ranking/index", "index/top"); }) BLOD.joinNode((msg) => { // 失效分区转换 if (msg.target.id == "bili_ad" || msg.target.className == "report-wrap-module elevator-module") this.fixNews(msg.target); // 覆盖个性化推荐 if (/bili-wrapper/.test(msg.target.className)) this.fixRecommand(); // 修复主页排行:电视剧、电影、纪录片 if (msg.target.id == "bili_movie" || msg.target.id == "bili_teleplay" || msg.target.id == "bili_documentary") this.fixRank(msg.target); }) } /** * 排行榜 */ rank() { try { BLOD.path.name = true; // 重写指示,有些操作无需再重写页面生效 let refer = document.referrer.split("/"), page; // 获取__INITIAL_STATE__ if (refer && refer[4] && refer[4] == "all") page = BLOD.jsonCheck(xhr.false(BLOD.objUrl("https://api.bilibili.com/x/web-interface/ranking/v2", { rid: refer[5], day: 3 }))); else page = BLOD.jsonCheck(xhr.false(BLOD.objUrl("https://api.bilibili.com/x/web-interface/ranking/v2", { rid: 0, day: 3 }))); // 重构__INITIAL_STATE__ page.data.list.forEach(((e, i, l) => { l[i] = Object.assign(l[i], { author: l[i].owner.name, coins: l[i].stat.coin, mid: l[i].owner.mid, play: l[i].stat.view, pts: l[i].score, trend: null, video_review: l[i].stat.danmaku }); if (l[i].others) { l[i].others.forEach(((e, i, l) => { l[i] = Object.assign(l[i], { author: l[i].owner.name, coins: l[i].stat.coin, mid: l[i].owner.mid, play: l[i].stat.view, pts: l[i].score, trend: null, video_review: l[i].stat.danmaku }); })); } })) BLOD.__INITIAL_STATE__ = { loading: false, rankRouteParams: { arc_type: 0, day: 3, rankTab: "all", rid: 1 * refer[5] || 0, season_type: 1 }, showTypes: true, times: [{ name: "日排行", value: 1 }, { name: "三日排行", value: 3 }, { name: "周排行", value: 7 }, { name: "月排行", value: 30 }], typeList: [{ name: "全部投稿", value: 0 }, { name: "近期投稿", value: 1 }] }; BLOD.__INITIAL_STATE__.channels = [{ name: "全站", tid: 0 }, { name: "动画", tid: 1 }, { name: "国创相关", tid: 168 }, { name: "音乐", tid: 3 }, { name: "舞蹈", tid: 129 }, { name: "游戏", tid: 4 }, { name: "知识", tid: 36 }, { name: "科技", tid: 188 }, { name: "生活", tid: 160 }, { name: "美食", tid: 211 }, { name: "鬼畜", tid: 119 }, { name: "时尚", tid: 155 }, { name: "娱乐", tid: 5 }, { name: "影视", tid: 181 }]; BLOD.__INITIAL_STATE__.rankList = page.data.list; BLOD.__INITIAL_STATE__.note = page.data.note; window.__INITIAL_STATE__ = BLOD.__INITIAL_STATE__; // 写入旧版__INITIAL_STATE__ BLOD.write(this.oldScript(BLOD.GM.getResourceText("ranking"))); // 重写排行榜 BLOD.addCss("@media screen and (min-width: 1400px){.main-inner {width: 1160px !important;}}"); // 修复自适应样式 } catch (e) { e = Array.isArray(e) ? e : [e]; toast.error("页面重写", ...e); } } /** * 直播页 */ live() { if (BLOD.config.reset.roomplay) BLOD.getVariable(window, "__NEPTUNE_IS_MY_WAIFU__", undefined, [undefined]); // 清除live缓存 if (config.reset.nop2p) { window.RTCPeerConnection = undefined; window.RTCDataChannel = () => { }; toast.warning("禁用直播间p2p上传!"); } if (config.reset.nosleep) { // 阻止直播间挂机检测 this.setInterval = setInterval; this.clock = 0; window.setInterval = (...args) => { if (args[1] && args[1] == 300000 && args[0] && args[0].toString() == "function(){e.triggerSleepCallback()}") { if (!this.clock) { toast.warning("成功阻止直播间挂机检测!", ...args); this.clock++; } return Number.MIN_VALUE; } return this.setInterval.call(window, ...args); } } if (config.reset.noanchor) BLOD.joinNode(() => BLOD.removeElement("anchor-guest-box-id", "id", null, null, () => toast.warning("拦截天选时刻!"))); if (config.reset.nopkvm) BLOD.joinNode(() => BLOD.removeElement("chaos-pk-vm", "id", null, null, () => toast.warning("拦截大乱斗!"))); BLOD.joinNode(() => BLOD.removeElement("web-player-icon-roomStatus", "class")); // 移除直播水印 if (config.reset.roomplay) BLOD.xhrhook((xhr, args) => { if (args[1].includes('api.live.bilibili.com/xlive/web-room/v2/index/getRoomPlayInfo')) { xhr.addEventListener('readystatechange', () => { if (xhr.readyState === 4) { try { let response = BLOD.jsonCheck(xhr.responseText); if (response.data) { response.data.live_status = 0; response.data.live_time = -1; response.data.playurl_info = null; } toast.warning("拦截直播间视频流!", "关闭【直播拦截】功能可恢复正常!") Object.defineProperty(xhr, 'response', { writable: true }); Object.defineProperty(xhr, 'responseText', { writable: true }); xhr.response = xhr.responseText = JSON.stringify(response); } catch (e) { e = Array.isArray(e) ? e : [e]; toast.error("直播拦截", ...e) } } }); } }) } /** * 专栏 */ read() { BLOD.path.name = true; // 重写指示,有些操作无需再重写页面生效 let page = xhr.false(location.href); // 获取页面数据 let data = page.includes("__INITIAL_STATE__=") ? JSON.parse(page.match(/INITIAL_STATE__=.+?\;\(function/)[0].replace(/INITIAL_STATE__=/, "").replace(/;\(function/, "")) : ""; //读取__INITIAL_STATE__ let bar = [ // bar库 [0, "推荐", "home"], [2, "动画", "douga"], [1, "游戏", "game"], [28, "影视", "cinephile"], [3, "生活", "life"], [29, "兴趣", "interest"], [16, "轻小说", "lightnovel"], [17, "科技", "technology"], [41, "笔记", "note"] ] let bars = bar.reduce((o, d) => { // 构造bar o = o + `${d[1]}`; return o; }, `
"; // 构造up主信息 let upinfo = ` `; // 构造标题 let head = `本文为我原创
`; // 文章本体 let tag = (data.readInfo.tags || []).reduce((o, d) => { // 构造tag o = o + `' + data.list[i].title + '
' + data.list[i].new_ep.index_show + ''; li.onmouseover = () => { fw = document.createElement("div"); fw.setAttribute("class", "bangumi-info-module"); fw.setAttribute("style", 'left: ' + li.getBoundingClientRect().left + 'px; top: ' + (BLOD.getTotalTop(li) - 150) + 'px;'); fw.innerHTML = '' + data.list[i].title + '
' + data.list[i].new_ep.index_show + '
${this.indexRecommend[i].title}
播放:${BLOD.unitFormat(this.indexRecommend[i].stat.view)}