// ==UserScript== // @name Bilibili 旧播放页 // @namespace MotooriKashin // @version 7.0.6 // @description 恢复Bilibili旧版页面,为了那些念旧的人。 // @author MotooriKashin,wly5556 // @homepage https://github.com/MotooriKashin/Bilibili-Old // @supportURL https://github.com/MotooriKashin/Bilibili-Old/issues // @icon https://static.hdslb.com/images/favicon.ico // @match *://*.bilibili.com/* // @connect * // @grant GM_xmlhttpRequest // @grant GM_getResourceText // @grant GM_getResourceURL // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_listValues // @grant GM.cookie // @run-at document-start // @license MIT // @resource index-icon.json https://www.bilibili.com/index/index-icon.json // @resource protobuf.js https://cdn.jsdelivr.net/npm/protobufjs@6.10.1/dist/protobuf.min.js // @resource comment.min.js https://cdn.jsdelivr.net/gh/MotooriKashin/Bilibili-Old@c74067196af49a16cb6e520661df7d4d1e7f04e5/src/comment.min.js // @resource bilibiliPlayer.js https://cdn.jsdelivr.net/gh/MotooriKashin/Bilibili-Old@bec3f065562e56374088e615d6ce89a986b3365b/dist/bilibiliPlayer.min.js // @resource comment.js https://cdn.jsdelivr.net/gh/MotooriKashin/Bilibili-Old@e34ba53279212adc855ff0f17fbdde5d61a4f11e/dist/comment.min.js // @downloadURL none // ==/UserScript== /** * 脚本设置接口,自动存储对于设置的修改 */ const config = new Proxy({}, { set: (_target, p, value) => { _target[p] = value; GM_setValue("config", _target); return true; } }); Object.entries(GM_getValue("config", {})).forEach(k => config[k[0]] = k[1]); /** * console封装,模块中请使用`debug`实例 */ class Debug { static log(...data) { console.log(`%c[${Format.timeFormat()}]`, "color: blue;", ...data); } static info(...data) { console.info(`%c[${Format.timeFormat()}]`, "color: green;", ...data); } static debug(...data) { console.debug(`[${Format.timeFormat()}]`, ...data); } static warn(...data) { console.warn(`[${Format.timeFormat()}]`, ...data); } static error(...data) { console.error(`[${Format.timeFormat()}]`, ...data); } } const debug = new Proxy(Debug, { apply: (target, thisArg, argArray) => { target.log(...argArray); } }); /** * URL处理函数 */ class Url { url = ""; search = ""; hash = ""; constructor(url) { const search = url.match(/(?<=\?)[A-Za-z0-9&=%\+\-_\.~!\*'\(\);@$,\[\]]+/g); this.search = search ? "?" + search.join("&") : ""; const hash = url.match(/(?<=\#)[A-Za-z0-9&=%\+\-_\.~!\*'\(\);@$,\[\]\/]+/g); this.hash = hash ? "#" + hash : ""; this.url = url.replace(/\?[A-Za-z0-9&=%\+\-_\.~!\*'\(\);@$,\[\]]+/g, "") .replace(/\#[A-Za-z0-9&=%\+\-_\.~!\*'\(\);@$,\[\]\/]+/g, ""); } /** * 提取url的查询参数为对象 * @returns 参数对象 */ getSearch() { if (this.search) { return this.search.substring(1).split("&").reduce((s, d) => { const arr = d.split("="); s[arr[0]] = arr[1]; return s; }, {}); } else return {}; } /** * 修改/添加url参数 * @param obj 参数对象 */ setSearch(obj) { let tar = this.getSearch(); tar = Object.assign(tar, obj); const result = Object.entries(tar).reduce((s, d) => { d[1] !== null && d[1] !== undefined && s.push(`${d[0]}=${d[1]}`); return s; }, []).join("&"); this.search = result ? "?" + result : ""; } /** * 转化为url字符串 * @returns url字符串 */ toJSON() { return ((this.url || "") + this.search + this.hash).replace(/^\?/, ""); } } /** * 格式化工具集 */ class Format { /** * 格式化时间 * @param time 时间戳 * @param type 是否包含年月日 * @returns 时:分:秒 | 年-月-日 时:分:秒 */ static timeFormat(time = new Date().getTime(), type) { let date = new Date(time), Y = date.getFullYear() + '-', M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-', D = (date.getDate() < 10 ? '0' + (date.getDate()) : date.getDate()) + ' ', h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':', m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) + ':', s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()); return type ? Y + M + D + h + m + s : h + m + s; } /** * 格式化字节 * @param size 字节/B * @returns n B | K | M | G */ static sizeFormat(size = 0) { let unit = ["B", "K", "M", "G"], i = unit.length - 1, dex = 1024 ** i, vor = 1000 ** i; while (dex > 1) { if (size >= vor) { size = Number((size / dex).toFixed(2)); break; } dex = dex / 1024; vor = vor / 1000; i--; } return size ? size + unit[i] : "N/A"; } /** * 格式化进位 * @param num 实数 * @returns n 万 | 亿 */ static unitFormat(num = 0) { num = 1 * num || 0; let unit = ["", "万", "亿"], i = unit.length - 1, dex = 10000 ** i; while (dex > 1) { if (num >= dex) { num = Number((num / dex).toFixed(1)); break; } dex = dex / 10000; i--; } return num + unit[i]; } /** * 冒泡排序 * @param arr 待排序数组 * @returns 排序结果 */ static bubbleSort(arr) { let temp; for (let i = 0; i < arr.length - 1; i++) { let bool = true; for (let j = 0; j < arr.length - 1 - i; j++) { if (arr[j] > arr[j + 1]) { temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; bool = false; } } if (bool) break; } return arr; } /** * 随机截取指定大小子数组 * @param arr 母数组 * @param num 子数组大小 * @returns 子数组 */ static randomArray(arr, num) { let out = []; num = num || 1; num = num < arr.length ? num : arr.length; while (out.length < num) { var temp = (Math.random() * arr.length) >> 0; out.push(arr.splice(temp, 1)[0]); } return out; } /** * search参数对象拼合回URL * @param url URL主体,可含search参数和锚 * @param obj search参数对象 * @returns 拼合的URL */ static objUrl(url = "", obj = {}) { const result = new Url(url); result.setSearch(obj); return result.toJSON(); } /** * 提取URL search参数对象 * @param url 原URL * @returns search参数对象 */ static urlObj(url = "") { return new Url(url).getSearch(); } /** * 秒数 -> hh:mm:ss * @param second 秒数 * @returns hh:mm:ss */ static s2hms(second) { const s = second % 60; let m = parseInt(String(second / 60)); const h = parseInt(String(m / 60)); m = m % 60; return (h > 0 ? h + ":" : "") + (h > 0 || m > 0 ? (Array(2).join('0') + m).slice(-2) + ":" : "") + (Array(2).join('0') + s).slice(-2); } /** * 格式化时间间隔,返回过去了多长时间 * timeFormat的再封装 * @param time 10/13位的时间戳 * @returns 过去了多长时间,当时间间隔超过一天时,直接返回timeFormat带年月日的结果 */ static intervalFormat(time) { time >= 1e11 && (time = Math.floor(time / 1e3)); const now = Math.floor((new Date).getTime() / 1e3); let t = new Date; if (t.setHours(0), t.setMinutes(0), t.setSeconds(0), (t = Math.floor(t.getTime() / 1e3)) < time && 0 <= now - time) { if (now - time <= 50) { var r = 10 * Math.floor((now - time) % 60 / 10); return (10 < time ? r : 10) + "秒前"; } return now - time < 3600 ? Math.floor((now - time) / 60) + "分钟前" : Math.floor((now - time) / 3600) + "小时前"; } return Format.timeFormat(time * 1e3, true); } } // GM系列高级API的封装 GM.xmlHttpRequest = GM_xmlhttpRequest; GM.getValue = GM_getValue; GM.setValue = GM_setValue; GM.deleteValue = GM_deleteValue; GM.listValues = GM_listValues; GM.getResourceText = GM_getResourceText; GM.getResourceURL = GM_getResourceText; GM.DOM = document; // 模块打包入口 const modules = {}; /** * 不可直接调用,请访问`toast`替代! */ class Toast { /** * 通知节点,初始化专用 */ static container; /** * 通知样式 */ static style; /** * 判定`body`是否存在 */ static check; /** * 通知节点,呈现时 */ static box; /** * 未呈现通知计数 */ static count = 0; /** * 动画呈现帧数 */ static sence = 60; static init() { this.container = document.createElement("div"); this.style = document.createElement("link"); this.container.setAttribute("id", "toast-container"); this.container.setAttribute("class", "toast-top-right"); this.style.setAttribute("rel", "stylesheet"); this.style.setAttribute("id", "toastr-style"); this.style.setAttribute("href", "//cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css"); } static show(type, ...msg) { if (config.toastcheck === false) return; if (!document.body) { if (this.check) return; return setTimeout(() => { this.check = true; this.show(type, ...msg); }); } document.querySelector("#toastr-style") || document.head.appendChild(this.style); document.querySelector("#toast-container") || document.body.appendChild(this.container); this.box = document.querySelector("#toast-container") || this.container; let item = document.createElement("div"); item.setAttribute("class", "toast toast-" + type); item.setAttribute("aria-live", "assertive"); item.setAttribute("style", "visibility: hidden;position: absolute"); setTimeout(() => { if (this.count > 0) this.count--; item = this.box.insertBefore(item, this.box.firstChild); item.appendChild(this.msg(...msg)); this.come(item); setTimeout(() => this.quit(item), (Number(config.toasttimeout) || 4) * 1000); }, this.count * (Number(config.toaststep) || 250)); this.count++; } static come(item, i = 0) { let height = item.clientHeight; item.setAttribute("style", "display: none;"); let timer = setInterval(() => { i++; item.setAttribute("style", "padding-top: " + i / 4 + "px;padding-bottom: " + i / 4 + "px;height: " + i / 60 * height + "px;"); if (i === this.sence) { clearInterval(timer); item.removeAttribute("style"); } }); } static quit(item, i = this.sence) { let height = item.clientHeight; let timer = setInterval(() => { i--; item.setAttribute("style", "padding-top: " + i / 4 + "px;padding-bottom: " + i / 4 + "px;height: " + i / 60 * height + "px;"); if (i === 0) { clearInterval(timer); item.remove(); if (!this.box.firstChild) this.box.remove(); } }); } static msg(...msg) { let div = document.createElement("div"); div.setAttribute("class", "toast-message"); div.innerHTML = msg.reduce((s, d, i) => { s = s + (i ? "
" : "") + String(d); return s; }, ""); return div; } constructor() { Toast.init(); } info(...msg) { debug.debug(...msg); Toast.show("info", ...msg); } success(...msg) { debug.log(...msg); Toast.show("success", ...msg); } warning(...msg) { debug.warn(...msg); Toast.show("warning", ...msg); } error(...msg) { debug.error(...msg); Toast.show("error", ...msg); } } new Toast(); const toast = new Proxy((...msg) => { debug.debug(...msg); Toast.show("info", ...msg); }, { get: (t, p) => { let result = () => { }; switch (p) { case "info": result = (...msg) => { debug.debug(...msg); Toast.show("info", ...msg); }; break; case "success": result = (...msg) => { debug.log(...msg); Toast.show("success", ...msg); }; break; case "warning": result = (...msg) => { debug.warn(...msg); Toast.show("warning", ...msg); }; break; case "error": result = (...msg) => { debug.error(...msg); Toast.show("error", ...msg); }; break; } return result; } }); /** * Xhr封装,模块内请使用`xhr`实例 */ class Xhr { static catches = []; static log = () => this.catches; /** * `XMLHttpRequest`的`Promise`封装 * @param details 以对象形式传递的参数,注意`onload`回调会覆盖Promise结果 * @returns `Promise`托管的请求结果或者报错信息,`async = false` 时除外,直接返回结果 */ static xhr(details) { details.method == "POST" && (details.headers = details.headers || {}, !details.headers["Content-Type"] && Reflect.set(details.headers, "Content-Type", "application/x-www-form-urlencoded")); if (details.hasOwnProperty("async") && Boolean(details.async) === false) { let xhr = new XMLHttpRequest(); xhr.open(details.method || 'GET', details.url, false); details.responseType && (xhr.responseType = details.responseType); details.credentials && (xhr.withCredentials = true); details.headers && (Object.entries(details.headers).forEach(d => xhr.setRequestHeader(d[0], d[1]))); details.timeout && (xhr.timeout = details.timeout); xhr.send(details.data); return xhr.response; } return new Promise((resolve, reject) => { let xhr = new XMLHttpRequest(); xhr.open(details.method || 'GET', details.url); details.responseType && (xhr.responseType = details.responseType); details.headers && (Object.entries(details.headers).forEach(d => xhr.setRequestHeader(d[0], d[1]))); details.credentials && (xhr.withCredentials = true); details.timeout && (xhr.timeout = details.timeout); xhr.onabort = details.onabort || ((ev) => reject(ev)); xhr.onerror = details.onerror || ((ev) => reject(ev)); details.onloadstart && (xhr.onloadstart = details.onloadstart); details.onprogress && (xhr.onprogress = details.onprogress); details.onreadystatechange && (xhr.onreadystatechange = details.onreadystatechange); xhr.ontimeout = details.ontimeout || ((ev) => reject(ev)); xhr.onload = details.onload || (() => resolve(xhr.response)); xhr.send(details.data); }); } /** * `GM_xmlhttpRequest`的`Promise`封装,用于跨域`XMLHttpRequest`请求 * @param details 以对象形式传递的参数,注意`onload`回调会覆盖Promise结果 * @returns `Promise`托管的请求结果或者报错信息 */ static GM(details) { return new Promise((resolve, reject) => { details.method = details.method || 'GET'; details.onload = details.onload || ((xhr) => { this.catches.push([details.url, xhr.response]); resolve(xhr.response); }); details.onerror = details.onerror || ((xhr) => { this.catches.push([details.url, xhr.response]); reject(xhr.response); }); GM.xmlHttpRequest(details); }); } /** * `XMLHttpRequest`的GET方法的快捷模式 * 将url独立为第一个参数,剩余参数放在第二个参数,方便快速发送ajax * **注意本方法默认带上了cookies,如需禁用请在details中提供headers对象并将其credentials属性置为false** * @param url url链接 * @param details url外的参数对象 * @returns `Promise`托管的请求结果或者报错信息,`async = false` 时除外,直接返回结果 */ static get(url, details = {}) { !Reflect.has(details, "credentials") && (details.credentials = true); // @ts-ignore return this.xhr({ url: url, ...details }); } /** * `XMLHttpRequest`的POST方法的快捷模式 * 将url、data,Content-Type分别独立为参数,剩余参数放在末尾,方便快速发送ajax * **注意本方法默认带上了cookies,如需禁用请在details中提供headers对象并将其credentials属性置为false** * @param url url链接 * @param data post数据 * @param contentType 发送数据使用的编码,默认"application/x-www-form-urlencoded" * @param details url、data外的参数对象 * @returns `Promise`托管的请求结果或者报错信息,`async = false` 时除外,直接返回结果 */ static post(url, data, contentType = "application/x-www-form-urlencoded", details = {}) { !Reflect.has(details, "credentials") && (details.credentials = true); details.headers = { "Content-Type": contentType, ...details.headers }; // @ts-ignore return this.xhr({ url: url, method: "POST", data: data, ...details }); } } const xhr = new Proxy(Xhr, { apply: (target, thisArg, argArray) => { return target.xhr.apply(target, argArray); } }); /**/modules["alert.css"] = /*** ./CSS/alert.css ***/ `.table { line-height : 14px; display : flex; flex-direction: column; box-sizing : border-box; top : 50%; background : #FFFFFF; box-shadow : 0 3px 12px 0 rgb(0 0 0 / 20%); border-radius : 10px; width : 300px; height : auto; padding : 18px; position : fixed; left : 50%; transform : translateX(-50%) translateY(-50%); z-index : 11124; } .title { line-height : 22px; margin-left : 2px; margin-bottom: 10px; font-size : 14px; } .text { margin-bottom: 3px; margin-left : 2px; } .act { line-height : 154%; align-items : center; border-radius : 4px; box-sizing : border-box; cursor : pointer; display : inline-flex; flex-shrink : 0; font-weight : 500; min-width : 5.14em; outline-width : 0; overflow : hidden; padding : 8px 16px; position : relative; user-select : none; border : none; color : #fff; justify-content: space-around; }`; /*!***********************!*/ /**/modules["animated-banner.css"] = /*** ./CSS/animated-banner.css ***/ `.animated-banner { position: absolute; top : 0; bottom : 0; left : 0; right : 0; } .animated-banner>.layer { position : absolute; left : 0; top : 0; height : 100%; width : 100%; display : flex; align-items : center; justify-content: center; overflow : hidden; } @keyframes banner-fade-in { 0% { opacity: 0; } 100% { opacity: 1; } } .animated-banner .layer { animation: banner-fade-in 0.7s; }`; /*!***********************!*/ /**/modules["avatarAnimation.css"] = /*** ./CSS/avatarAnimation.css ***/ `/* 鼠标放在顶栏上的动效 */ .bili-header-m .profile-info .i-face .face { border: 0 } .bili-header-m .profile-info .i-face .pendant { transform : scale(0.5); width : 112px; height : 112px; left : -41px; bottom : -46px; opacity : 0; transition: opacity .1s ease-in } .bili-header-m .profile-info.on .i-face { left : 8px; top : 0; height : 32px; width : 32px; transform : translateY(10px) translateX(-16px) scale(2); transform-origin: top left } .bili-header-m .profile-info.on .i-face .legalize { transform: scale(0.5) translate(10px, 15px) } .bili-header-m .profile-info.on .i-face .pendant { opacity: 1 } .bili-header-m .profile-info.on .i-face .face { border : 0; box-shadow: 0 0 0 2px #fff } .bili-header-m .profile-info.on .i-face.scale-in { transform: translateY(5px) translateX(-10px) scale(1.75) } .bili-header-m .profile-info.on .scale-in .face { height: 32px; width : 32px } .bili-header-m .profile-info.on .i-face.scale-in .legalize { transform: scale(0.5) translate(38px, 48px) }`; /*!***********************!*/ /**/modules["bgray-btn.css"] = /*** ./CSS/bgray-btn.css ***/ `.player-wrapper { position: relative; } .player-fullscreen-fix { position: fixed; top : 0; left : 0; margin : 0; padding : 0; width : 100%; height : 100%; } .player-fullscreen-fix #bofqi .player { position : fixed !important; border-radius: 0; z-index : 100000 !important; left : 0; top : 0; width : 100% !important; height : 100% !important; } .bgray-btn-wrap { position : absolute; top : 10px; left : 50%; margin-left: 490px; width : 70px; height : 200px; } .widescreen .bgray-btn-wrap { margin-left: 580px; } .bgray-btn { transition : all 0.3s; cursor : pointer; margin : 10px 0; background-color: #fff; text-align : center; padding : 7px 5px; display : block; left : 100%; font-size : 12px; line-height : 12px; margin-left : 10px; width : 20px; border-radius : 4px; border : 1px solid #e5e9ef; color : #99a2aa; } .bgray-btn-feedback { height : 72px; margin-bottom: 5px; } .bgray-btn-help { height : 24px; margin-top: 5px; } .bgray-btn:hover { color : #6d757a; border-color: #6d757a; } .bgray-btn.player-feedback-disable { color: #ccd0d7 } .bgray-btn.player-feedback-disable:hover { color : #ccd0d7; border-color: #ccd0d7; } .bgray-btn.player-feedback-disable { color: #ccd0d7 } .bgray-btn.player-feedback-disable:hover { color : #ccd0d7; border-color: #ccd0d7; } .bgray-btn.active { cursor : default; color : #00a1d6; border-color: #00a1d6; } .bgray-line { display : none; width : 42px; margin : 0 auto; border-bottom: 1px solid #e5e9ef; } .bgray-btn { display: none; } .bgray-btn.show { display: block; } @media screen and (min-width: 1400px) { .bgray-btn-wrap { margin-left: 580px; } } .bgray-btn.happyfoolsday { line-height : 13px; background-color: #00a1d6; border-color : #00a1d6; color : #fff; } .bgray-btn.happyfoolsday:hover { background-color: #00b5e5; border-color : #00b5e5; color : #fff; }`; /*!***********************!*/ /**/modules["bofqi.css"] = /*** ./CSS/bofqi.css ***/ `#bofqi .player { width : 980px; height : 620px; display: block; } @media screen and (min-width:1400px) { #bofqi .player { width : 1160px; height: 720px } }`; /*!***********************!*/ /**/modules["button.css"] = /*** ./CSS/button.css ***/ `.button { line-height : 154%; align-items : center; border-radius : 4px; box-sizing : border-box; cursor : pointer; display : inline-flex; flex-shrink : 0; font-weight : 500; height : 32px; justify-content: center; min-width : 5.14em; outline-width : 0; overflow : hidden; padding : 8px 16px; position : relative; user-select : none; } .button { background-color: #fff; color : rgb(26, 115, 232); border : 1px solid rgba(0, 0, 0, 6%); } .button:hover { background-color: rgba(26, 115, 232, 6%); } .button:active { box-shadow: 0 0 1px 1px rgba(0, 0, 0, 10%); } .button[disabled] { pointer-events : none; background-color: rgba(239, 239, 239, 0.3); border : 1px solid rgba(118, 118, 118, 0.3); color : rgba(16, 16, 16, 0.3); }`; /*!***********************!*/ /**/modules["checkbox.css"] = /*** ./CSS/checkbox.css ***/ `/* 复选框 */ .box { display: inline-flex; } .checkbox { align-items: center; display : flex; min-height : auto; padding : 0; cursor : pointer; } .checkbox .checklabel { height : 16px; margin-block-start: 0px; position : relative; width : 16px; border-radius : 50%; } .checklabel .disc-border { border : 2px solid rgb(95, 99, 104); box-sizing : border-box; height : 16px; width : 16px; border-radius: 50%; } .checklabel .disc-border[checked] { border-color: rgb(26, 115, 232); } .checklabel .disc { background-color: transparent; position : absolute; top : 0; transform : scale(0); transition : border-color 200ms, transform 200ms; box-sizing : border-box; height : 16px; width : 16px; border-radius : 50%; } .checklabel .disc[checked] { background-color: rgb(26, 115, 232); transform : scale(0.5); } .checkbox .checkvalue { flex : 1; margin-inline-start: 5px; margin-inline-end : 5px; }`; /*!***********************!*/ /**/modules["closedCaption.css"] = /*** ./CSS/closedCaption.css ***/ `/* CC字幕相关样式 */ /*对齐,悬停按钮显示菜单*/ #subtitle-setting-panel>div>* { margin-right: 5px; } #bilibili-player-subtitle-btn:hover>#subtitle-setting-panel { display: block !important; } /*滑动选择样式*/ #subtitle-setting-panel input[type="range"] { background-color : #ebeff4; -webkit-appearance: none; height : 4px; transform : translateY(-4px); } #subtitle-setting-panel input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; height : 15px; width : 15px; background : #fff; border-radius : 15px; border : 1px solid; } /*复选框和其对应标签样式*/ #subtitle-setting-panel input[type="checkbox"] { display: none; } #subtitle-setting-panel input~label { cursor: pointer; } #subtitle-setting-panel input:checked~label:before { content: '\\2714'; } #subtitle-setting-panel input~label:before { width : 12px; height : 12px; line-height : 14px; vertical-align: text-bottom; border-radius : 3px; border : 1px solid #d3d3d3; display : inline-block; text-align : center; content : ' '; } /*悬停显示下拉框样式*/ #subtitle-setting-panel .bpui-selectmenu:hover .bpui-selectmenu-list { display: block; } /*滚动条样式*/ #subtitle-setting-panel ::-webkit-scrollbar { width: 7px; } #subtitle-setting-panel ::-webkit-scrollbar-track { border-radius : 4px; background-color: #EEE; } #subtitle-setting-panel ::-webkit-scrollbar-thumb { border-radius : 4px; background-color: #999; }`; /*!***********************!*/ /**/modules["commandDm.css"] = /*** ./CSS/commandDm.css ***/ `.commandDm-popup { border-radius : 1rem; background-color: #f5f5f5; position : absolute; cursor : default; opacity : 0; transition : opacity 0.2s; padding : 0.8rem 1rem; } .commandDm-popup.on { opacity: 1; } .vote-dialog { overflow : hidden; display : flex; flex-direction: column; } .vote-panel { display : flex; justify-content: space-between; width : 100%; } .vote-title, .grade-title { font-weight : bolder; margin-bottom: 0.5rem; } .vote-option { display : flex; flex-direction: column; width : 100%; } .vote-button { text-align : center; min-width : 85px; display : inline-block; padding : 0.3rem 2rem; border : 1px solid #00a1d6; border-radius : 5px; margin : 0.2rem 0; background-color: #fff; cursor : pointer; } .vote-button:hover { background-color: #1baada; color : #f5f5f5; transition : all 0.15s ease-out; } .vote-button::before { position: absolute; padding : 0 1.8rem; left : 0; content : attr(idx); } .vote-progress-bg { border-radius : 5px; min-width : 85px; margin : 0.2rem 0; border : 1px solid #1a1a1a6b; background-color: white; position : relative; } .vote-progress { transition : width 0.3s, background-color 0.2s; animation : opacity-animation 0.5s; overflow : hidden; display : inline-block; border-radius : 4px 0 0 4px; background-color: #d3d3d3; text-align : left; overflow : visible; position : relative; } .vote-progress-blue { background-color: #9fdef3; } .vote-progress-desc { display: inline-block; margin : 0.3rem 0.8rem; } @keyframes opacity-animation { from { opacity: 0; } to { opacity: 1; } } .vote-count { display : inline-block; position: absolute; right : 0.8rem; top : 0.3rem; } .vote-count::after { content: "票"; } .bilibili-player-video-popup { z-index : 100; position : absolute; top : 0; left : 0; width : 100%; height : 100%; pointer-events: none; } .bilibili-player-video-popup>* { pointer-events: all; } .link-button { animation : opacity-animation 0.2s; position : absolute; left : 40%; top : 20%; background-color: #f5f5f5; padding : 0.4rem 1rem; border-radius : 0.6rem; font-size : large; box-shadow : #888888c7 0px 0px 6px; } .link-button:hover { color : #00a1d6; cursor: pointer; } .link-button>* { vertical-align: middle; } .link-button>img { transform: scale(0.7) translateY(-1px); } .danmaku-up-icon::before { content : "UP主"; background-color: #00a1d6; border-radius : 5px; font-size : 0.8em; padding : 0.1em; transform : translateY(-0.1em); display : inline-block; box-shadow : #888888c7 0px 0px 6px; } .grade-score-area>div { display : inline-block; position : relative; width : 41px; transition: width 0.3s; } .grade-score-area.pointer { cursor: pointer; } .grade-score-area>div:last-child { width: 20px; } .grade-score-area .score-button { filter: grayscale(1); } .grade-score-area .highlight .score-button { filter: none; } .grade-score-area .bg { position : absolute; left : 0; filter : blur(9px); visibility: hidden; } .grade-score-area .highlight .bg { visibility: visible; } .grade-score-info { position: absolute; right : 1rem; bottom : 0.6rem; opacity : 0; } @keyframes grade-score-showup { 0% { opacity : 0; transform: translateY(5px); } 100% { opacity : 1; transform: translateY(0); } } @keyframes grade-score-hit { 0% { filter: brightness(1); } 30% { filter: brightness(1.5); } 100% { filter: brightness(1); } }`; /*!***********************!*/ /**/modules["comment.css"] = /*** ./CSS/comment.css ***/ `.bb-comment .comment-header .header-page, .comment-bilibili-fold .comment-header .header-page { float : right; line-height: 36px; } .bb-comment .comment-list .list-item .user .text-con, .comment-bilibili-fold .comment-list .list-item .user .text-con { margin-left: initial; } .bb-comment .comment-list .list-item .reply-box .reply-item .reply-con .user>a, .comment-bilibili-fold .comment-list .list-item .reply-box .reply-item .reply-con .user>a { margin-left: initial; } .user-card .info .user .vip-icon { max-width : 58px; height : 16px; border-radius : 2px; margin-left : 8px; background-color: #FF6699; font-size : 12px; font-weight : 400; color : #fff; white-space : nowrap; padding : 1px; padding-inline : 4px; } .user-card .info .verify { color : #9499A0; line-height: 17px; margin-top : 11px; } .user-card .info .verify .auth { display : inline-block; vertical-align: bottom; position : relative; left : -3px; width : 16px; height : 16px; } .reply-item .reply-con .user .stick { zoom: 0.9; }`; /*!***********************!*/ /**/modules["danmakuHashId.css"] = /*** ./CSS/danmakuHashId.css ***/ `/* 反查弹幕发送者相关样式 */ .bb-comment, .comment-bilibili-fold { font-family: Microsoft YaHei, Arial, Helvetica, sans-serif; font-size : 0; zoom : 1; min-height : 100px; background : #fff; } .bb-comment .comment-list, .comment-bilibili-fold .comment-list { padding-top: 20px; } .bb-comment *, .comment-bilibili-fold * { box-sizing: content-box; } .bb-comment .comment-list .list-item .reply-box .reply-item .reply-face, .comment-bilibili-fold .comment-list .list-item .reply-box .reply-item .reply-face { display : inline-block; position : relative; margin-right : 10px; vertical-align: top; } .bb-comment .comment-list .list-item .reply-box .reply-item .reply-face img, .comment-bilibili-fold .comment-list .list-item .reply-box .reply-item .reply-face img { width : 24px; height : 24px; border-radius: 50%; } .bb-comment .comment-list .list-item .reply-box .reply-item .reply-con, .comment-bilibili-fold .comment-list .list-item .reply-box .reply-item .reply-con { display: inline-block; width : calc(100% - 34px); } .bb-comment .comment-list .list-item .user, .comment-bilibili-fold .comment-list .list-item .user { font-size : 12px; font-weight : 700; line-height : 18px; padding-bottom: 4px; display : block; word-wrap : break-word; position : relative; } .bb-comment .comment-list .list-item .reply-box .reply-item .reply-con .user .name, .comment-bilibili-fold .comment-list .list-item .reply-box .reply-item .reply-con .user .name { position: relative; top : -1px; } .bb-comment .comment-list .list-item .reply-box .reply-item .level, .comment-bilibili-fold .comment-list .list-item .reply-box .reply-item .level { margin: 0 15px 0 8px; } .bb-comment .comment-list .list-item .user .level.l0, .comment-bilibili-fold .comment-list .list-item .user .level.l0 { background-position: -23px -28px } .bb-comment .comment-list .list-item .user .level.l1, .comment-bilibili-fold .comment-list .list-item .user .level.l1 { background-position: -23px -92px } .bb-comment .comment-list .list-item .user .level.l2, .comment-bilibili-fold .comment-list .list-item .user .level.l2 { background-position: -23px -156px } .bb-comment .comment-list .list-item .user .level.l3, .comment-bilibili-fold .comment-list .list-item .user .level.l3 { background-position: -23px -220px } .bb-comment .comment-list .list-item .user .level.l4, .comment-bilibili-fold .comment-list .list-item .user .level.l4 { background-position: -23px -284px } .bb-comment .comment-list .list-item .user .level.l5, .comment-bilibili-fold .comment-list .list-item .user .level.l5 { background-position: -23px -348px } .bb-comment .comment-list .list-item .user .level.l6, .comment-bilibili-fold .comment-list .list-item .user .level.l6 { background-position: -23px -412px } .bb-comment .comment-list .list-item .user .level.l7, .comment-bilibili-fold .comment-list .list-item .user .level.l7 { background-position: -23px -476px } .bb-comment .comment-list .list-item .user .level.l8, .comment-bilibili-fold .comment-list .list-item .user .level.l8 { background-position: -23px -540px } .bb-comment .comment-list .list-item .user .level.l9, .comment-bilibili-fold .comment-list .list-item .user .level.l9 { background-position: -23px -604px } .bb-comment .comment-list .list-item .user .level, .comment-bilibili-fold .comment-list .list-item .user .level { display : inline-block; width : 19px; height : 9px; vertical-align: middle; margin : 0 8px; background : url(data:image/png;base64,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) no-repeat; }`; /*!***********************!*/ /**/modules["download.css"] = /*** ./CSS/download.css ***/ `.table { position : fixed; z-index : 11113; bottom : 0; width : 100%; min-height : 50px; display : flex; box-sizing : border-box; background : #fff; border-radius : 8px; box-shadow : 0 6px 12px 0 rgba(106, 115, 133, 22%); transition : transform 0.3s ease-in; flex-wrap : wrap; align-content : center; justify-content: center; align-items : center; } .cell { background-color: #fff; color : #000 !important; border : #ccc 1px solid; border-radius : 3px; display : flex; margin : 3px; flex-wrap : wrap; align-content : center; justify-content : center; align-items : center; flex-direction : row; } .type { color : #000 !important; display : table-cell; min-width : 1.5em; text-align : center; vertical-align: middle; padding : 10px 3px; } .item { display : table-cell; text-decoration: none; padding : 3px; cursor : pointer; color : #1184B4; } .item:hover { color: #FE3676; } .up { color : #fff !important; text-align : center; padding : 1px 3px; background-color: #777; } .down { font-size : 90%; margin-top: 2px; text-align: center; padding : 1px 3px; }`; /*!***********************!*/ /**/modules["hr.css"] = /*** ./CSS/hr.css ***/ `.hr { display : flex; align-items : center; grid-gap : 0; gap : 0; justify-content : space-between; flex-shrink : 0; height : 1px; background-color: rgba(136, 136, 136, 0.1); width : 100%; margin-bottom : 12px; }`; /*!***********************!*/ /**/modules["icon.css"] = /*** ./CSS/icon.css ***/ `.icon { align-items : center; border-radius : 50%; display : flex; height : 20px; justify-content: center; position : relative; width : 20px; box-sizing : content-box; background : none; cursor : pointer; }`; /*!***********************!*/ /**/modules["imroot.css"] = /*** ./CSS/imroot.css ***/ `/* 修复顶栏样式 */ .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; }`; /*!***********************!*/ /**/modules["input.css"] = /*** ./CSS/input.css ***/ `/* 输入框 */ .input { align-items : center; display : flex; justify-content : space-between; position : relative; background-color : transparent; box-sizing : border-box; padding : 0; flex : 1; flex-basis : 0.000000001px; padding-block-end : 12px; padding-block-start: 12px; } .input input { background-color : transparent; box-sizing : border-box; font-family : inherit; font-size : inherit; font-weight : inherit; line-height : inherit; min-height : auto; outline : none; padding-bottom : 6px; padding-inline-end : 8px; padding-inline-start: 8px; padding-top : 6px; text-align : inherit; text-overflow : ellipsis; width : 100%; border-radius : 4px; border : 1px solid rgba(136, 136, 136, 0.13333); box-shadow : 0 4px 12px 0 rgb(0, 0, 0, 5%); transition : box-shadow 120ms ease 180ms; } .input input:focus { box-shadow: inset 0 0 1px 1px rgba(26, 115, 232, 80%); } .input .icon { cursor : pointer; outline : none; padding : 0; pointer-events : auto; position : absolute; right : 12px; background-color: white; } .input .icon:hover { background-color: rgba(0, 0, 0, 10%); box-shadow : 0 1 12px 12px rgb(0, 0, 0, 10%); }`; /*!***********************!*/ /**/modules["message.css"] = /*** ./CSS/message.css ***/ `/* 修复消息页样式 */ .container[data-v-6969394c] { height: calc(100vh - 42px) !important; } .container[data-v-1c9150a9] { height: calc(100vh - 42px) !important; }`; /*!***********************!*/ /**/modules["mini-bofqi.css"] = /*** ./CSS/mini-bofqi.css ***/ `/* 修正稍后再看迷你播放器样式 */ .bilibili-player .bilibili-player-area .bilibili-player-video-wrap.mini-player .bilibili-player-video-danmaku { top : 30px; height: 240px; }`; /*!***********************!*/ /**/modules["oldReplySort.css"] = /*** ./CSS/oldReplySort.css ***/ `.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; }`; /*!***********************!*/ /**/modules["progress.css"] = /*** ./CSS/progress.css ***/ `.progress { --paper-progress-active-color : rgb(26, 115, 232); --paper-progress-container-color: rgb(223, 222, 223); width : auto; } .progressContainer { background: rgb(223, 222, 223); height : 4px; position : relative; } .secondaryProgress, .primaryProgress { position : absolute; top : 0; right : 0; bottom : 0; left : 0; transform-origin: left center; transform : scaleX(0); will-change : transform; } .secondaryProgress { background: rgb(183, 225, 205); } .primaryProgress { background: rgb(26, 115, 232); } .progressTag { width : 100%; padding-top : 6px; display : inline-flex; justify-content: space-between; }`; /*!***********************!*/ /**/modules["select.css"] = /*** ./CSS/select.css ***/ `/* 下拉列表 */ .select { align-items: center; display : inline-flex; } select { background-color : rgb(241, 243, 244); background-size : 10px; border : none; border-radius : 4px; color : rgb(32, 33, 36); cursor : pointer; font-family : inherit; font-size : inherit; line-height : inherit; max-width : 100%; outline : none; padding-bottom : 6px; padding-inline-end : 21px; padding-inline-start: 8px; padding-top : 6px; width : 200px; } option { background-color: #fff; }`; /*!***********************!*/ /**/modules["switch.css"] = /*** ./CSS/switch.css ***/ `/* 滑块开关 */ .switch { cursor : pointer; display : block; min-width: 34px; outline : none; position : relative; width : 34px; } .bar { background-color: rgb(189, 193, 198); border-radius : 8px; height : 12px; left : 3px; position : absolute; top : 2px; transition : background-color linear 80ms; width : 28px; z-index : 0; } .bar[checked] { background-color: rgb(26, 115, 232); opacity : 0.5; } .bar:active { box-shadow: 0 0 1px 1px rgba(26, 115, 232, 80%); } .knob { background-color: #fff; border-radius : 50%; box-shadow : 0 1px 3px 0 rgba(0, 0, 0, 40%); display : block; height : 16px; position : relative; transition : transform linear 80ms, background-color linear 80ms; width : 16px; z-index : 1; } .knob[checked] { background-color: rgb(26, 115, 232); transform : translate3d(18px, 0, 0); } .knob:active { box-shadow: 0 0 1px 1px rgba(26, 115, 232, 80%); } .knob i { color : rgba(128, 134, 139, 15%); height : 40px; left : -12px; pointer-events: none; top : -12px; transition : color linear 80ms; width : 40px; border-radius : 50%; bottom : 0; display : block; overflow : hidden; position : absolute; right : 0; transform : translate3d(0, 0, 0); } .knob i[checked] { color: rgb(26, 115, 232); } .knob i:active { box-shadow: 0 0 1px 1px rgba(26, 115, 232, 80%); }`; /*!***********************!*/ /**/modules["ui-action.css"] = /*** ./CSS/ui-action.css ***/ `.contain { align-items : center; border-top : 1px solid rgba(0, 0, 0, 6%); display : flex; min-height : 24px; padding : 0 20px; flex-wrap : wrap; justify-content : flex-end; background-color: transparent !important; } .label { flex : 1; flex-basis : 0.000000001px; padding-block-end : 12px; padding-block-start : 12px; padding-inline-start: 12px; } .sub { color : rgb(95, 99, 104); font-weight: 400; } .button, .action { line-height : 154%; align-items : center; border-radius : 4px; box-sizing : border-box; cursor : pointer; display : inline-flex; flex-shrink : 0; font-weight : 500; height : 32px; justify-content: center; min-width : 5.14em; outline-width : 0; overflow : hidden; padding : 8px 16px; position : relative; user-select : none; } .action { border : none; background-color: rgb(26, 115, 232); color : #fff; } .button { background-color: #fff; color : rgb(26, 115, 232); border : 1px solid rgba(0, 0, 0, 6%); } .action:hover { background-color: rgb(72, 115, 232); } .button:hover { background-color: rgba(26, 115, 232, 6%); } .action:active { box-shadow: 0 0 1px 1px rgba(72, 115, 232, 80%); } .button:active { box-shadow: 0 0 1px 1px rgba(0, 0, 0, 10%); } .button[disabled], .action[disabled] { pointer-events : none; background-color: rgba(19, 1, 1, 0.1); border : 1px solid rgba(0, 0, 0, 0.1); color : white; }`; /*!***********************!*/ /**/modules["ui-contain.css"] = /*** ./CSS/ui-contain.css ***/ `.contain { margin-bottom : 3px; padding-inline-start: 20px; padding-inline-end : 20px; display : flex; flex-direction : column; outline : none; position : relative; } .header .title { color : #000; font-size : 108%; font-weight : 400; letter-spacing: 0.25px; margin-bottom : 12px; margin-top : 21px; outline : none; padding-bottom: 4px; padding-top : 8px; } .card { border-radius: 4px; box-shadow : 0px 0px 1px 1px rgba(60, 64, 67, 30%); flex : 1; color : #000; line-height : 154%; user-select : text; }`; /*!***********************!*/ /**/modules["ui-file.css"] = /*** ./CSS/ui-file.css ***/ `.contain { align-items : center; border-top : 1px solid rgba(0, 0, 0, 6%); display : flex; min-height : 24px; padding : 0 20px; flex-wrap : wrap; justify-content : flex-end; background-color: transparent !important; } .label { flex : 1; flex-basis : 0.000000001px; padding-block-end : 12px; padding-block-start : 12px; padding-inline-start: 12px; } .sub { color : rgb(95, 99, 104); font-weight: 400; } .button, .action { line-height : 154%; align-items : center; border-radius : 4px; box-sizing : border-box; cursor : pointer; display : inline-flex; flex-shrink : 0; font-weight : 500; height : 32px; justify-content: center; min-width : 5.14em; outline-width : 0; overflow : hidden; padding : 8px 16px; position : relative; user-select : none; } .action { border : none; background-color: rgb(26, 115, 232); color : #fff; } .button { background-color: #fff; color : rgb(26, 115, 232); border : 1px solid rgba(0, 0, 0, 6%); } .action:hover { background-color: rgb(72, 115, 232); } .button:hover { background-color: rgba(26, 115, 232, 6%); } .action:active { box-shadow: 0 0 1px 1px rgba(72, 115, 232, 80%); } .button:active { box-shadow: 0 0 1px 1px rgba(0, 0, 0, 10%); } .button[disabled], .action[disabled] { pointer-events : none; background-color: rgba(19, 1, 1, 0.1); border : 1px solid rgba(0, 0, 0, 0.1); color : white; }`; /*!***********************!*/ /**/modules["ui-float.css"] = /*** ./CSS/ui-float.css ***/ `.float { top : 0; right : 0; position : fixed; z-index : 11111; min-width : 40px; min-height : 30px; display : block; padding : 8px; box-sizing : border-box; background : #fff; border : 1px solid #e9eaec; border-radius : 8px; box-shadow : 0 6px 12px 0 rgb(106, 115, 133, 22%); user-select : text; pointer-events: none; } .arrow { left : 16%; top : 100%; width : 0; height : 0; border-left : 4px solid transparent; border-right: 4px solid transparent; border-top : 8px solid #fff; position : absolute; user-select : text; } .message { margin-top : -4px; box-sizing : border-box; height : 100%; position : relative; user-select: text; word-wrap : break-word; word-break : break-all; font-size : 12px; line-height: 1.15; }`; /*!***********************!*/ /**/modules["ui-input.css"] = /*** ./CSS/ui-input.css ***/ `.contain { align-items : center; border-top : 1px solid rgba(0, 0, 0, 6%); display : flex; min-height : 24px; padding : 0 20px; flex-wrap : wrap; justify-content : flex-end; background-color: transparent !important; } .label { flex : 1; flex-basis : 0.000000001px; padding-block-end : 12px; padding-block-start : 12px; padding-inline-start: 12px; } .sub { color : rgb(95, 99, 104); font-weight: 400; } .textbox { align-items : center; display : flex; justify-content : space-between; position : relative; background-color : transparent; box-sizing : border-box; padding : 0; flex : 1; flex-basis : 0.000000001px; padding-block-end : 12px; padding-block-start: 12px; } .textbox input { background-color : transparent; box-sizing : border-box; font-family : inherit; font-size : inherit; font-weight : inherit; line-height : inherit; min-height : auto; outline : none; padding-bottom : 6px; padding-inline-end : 8px; padding-inline-start: 8px; padding-top : 6px; text-align : inherit; text-overflow : ellipsis; width : 100%; border-radius : 4px; border : 1px solid rgba(136, 136, 136, 0.13333); box-shadow : 0 4px 12px 0 rgb(0, 0, 0, 5%); transition : box-shadow 120ms ease 180ms; } .textbox input:focus { box-shadow: inset 0 0 1px 1px rgba(26, 115, 232, 80%); } .textbox .icon { cursor : pointer; outline : none; padding : 0; pointer-events : auto; position : absolute; right : 12px; background-color: white; } .textbox .icon:hover { background-color: rgba(0, 0, 0, 10%); box-shadow : 0 1 12px 12px rgb(0, 0, 0, 10%); } .button, .action { line-height : 154%; align-items : center; border-radius : 4px; box-sizing : border-box; cursor : pointer; display : inline-flex; flex-shrink : 0; font-weight : 500; height : 32px; justify-content: center; min-width : 5.14em; outline-width : 0; overflow : hidden; padding : 8px 16px; position : relative; user-select : none; } .action { border : none; background-color: rgb(26, 115, 232); color : #fff; } .button { background-color: #fff; color : rgb(26, 115, 232); border : 1px solid rgba(0, 0, 0, 6%); } .action:hover { background-color: rgb(72, 115, 232); } .button:hover { background-color: rgba(26, 115, 232, 6%); } .action:active { box-shadow: 0 0 1px 1px rgba(72, 115, 232, 80%); } .button:active { box-shadow: 0 0 1px 1px rgba(0, 0, 0, 10%); } .button[disabled], .action[disabled] { pointer-events : none; background-color: rgba(19, 1, 1, 0.1); border : 1px solid rgba(0, 0, 0, 0.1); color : white; }`; /*!***********************!*/ /**/modules["ui-item.css"] = /*** ./CSS/ui-item.css ***/ `/* 菜单项容器 */ .contain { align-items : center; border-top : 1px solid rgba(0, 0, 0, 6%); display : flex; min-height : 24px; padding : 0 20px; flex-wrap : wrap; justify-content : flex-end; background-color: transparent !important; } .label { flex : 1; flex-basis : 0.000000001px; padding-block-end : 12px; padding-block-start : 12px; padding-inline-start: 12px; } .sub { color : rgb(95, 99, 104); font-weight: 400; }`; /*!***********************!*/ /**/modules["ui-menu.css"] = /*** ./CSS/ui-menu.css ***/ `.menuitem { align-items : center; display : flex; font-weight : 500; margin-inline-end : 2px; margin-inline-start : 1px; min-height : 20px; padding-bottom : 10px; padding-inline-start: 23px; padding-top : 10px; cursor : pointer; } .menuitem:hover { background-color: rgb(0, 0, 0, 6%); } .menuitem>div { padding-inline-end: 12px; }`; /*!***********************!*/ /**/modules["ui-picture.css"] = /*** ./CSS/ui-picture.css ***/ `.contain { align-items : center; border-top : 1px solid rgba(0, 0, 0, 6%); display : flex; min-height : 24px; padding : 0 20px; flex-wrap : wrap; justify-content : center; background-color: transparent !important; line-height : 0; max-height : 62px; } .contain img { border-radius: 4px; width : 100%; max-height : 62px; }`; /*!***********************!*/ /**/modules["ui-popup-box.css"] = /*** ./CSS/ui-popup-box.css ***/ `.box { top : 50%; left : 50%; transform : translateX(-50%) translateY(-50%); transition : 0.3s cubic-bezier(0.22, 0.61, 0.36, 1); padding : 12px; background-color: #fff; color : black; border-radius : 8px; box-shadow : 0 4px 12px 0 rgb(0 0 0 / 5%); border : 1px solid rgba(136, 136, 136, 0.13333); box-sizing : border-box; position : fixed; font-size : 13px; z-index : 11115; line-height : 14px; } .contain { display : flex; flex-direction: column; height : 100%; } *::-webkit-scrollbar { width : 0 !important; height: 0 !important; }`; /*!***********************!*/ /**/modules["ui-sort-body.css"] = /*** ./CSS/ui-sort-body.css ***/ `contain { display : block; padding-block-end : 0; padding-block-start : 0; padding-inline-end : 20px; padding-inline-start: 20px; border-top : 1px solid rgba(0, 0, 0, 6%); }`; /*!***********************!*/ /**/modules["ui-sort-head.css"] = /*** ./CSS/ui-sort-head.css ***/ `.contain { align-items : center; border-top : 1px solid rgba(0, 0, 0, 6%); display : flex; min-height : 24px; padding : 0 20px; flex-wrap : wrap; justify-content : flex-end; background-color: transparent !important; } .label { flex : 1; flex-basis : 0.000000001px; padding-block-end : 12px; padding-block-start : 12px; padding-inline-start: 12px; } .sub { color : rgb(95, 99, 104); font-weight: 400; } .anchor { cursor : pointer; transition: transform 120ms ease 180ms, box-shadow 120ms ease 180ms; } .anchor[checked] { transform: rotateX(180deg); } .anchor:hover { box-shadow: 0 0 4px 4px rgba(241, 243, 244, 80%); }`; /*!***********************!*/ /**/modules["ui-stage.css"] = /*** ./CSS/ui-stage.css ***/ `.stage { position : fixed; right : 40px; bottom : 60px; height : 20px; width : 20px; border : 1px solid #e9eaec; border-radius: 50%; box-shadow : 0 0 12px 4px rgb(106, 115, 133, 22%); padding : 10px; cursor : pointer; animation : roll 1s ease-out; transition : opacity 0.3s ease-out; background : none; z-index : 11110; } .classical { box-sizing : content-box; color : #fff; background-color : #fff; border-radius : 5px; position : fixed; bottom : 65px; width : 56px; height : 40px; transition : right 0.7s; -moz-transition : right 0.7s; -webkit-transition: right 0.7s; -o-transition : right 0.7s; z-index : 11110; padding : 4px; right : -54px; } .classical:hover { right : 0px; box-shadow: rgba(0, 85, 255, 0.098) 0px 0px 20px 0px; border : 1px solid rgb(233, 234, 236); } .classical i { background-position: -471px -982px; display : block; width : 20px; height : 20px; transition : 0.2s; background-image : url(//static.hdslb.com/images/base/icons.png); margin : auto; } .classical span { font-size : 14px; display : block; width : 50%; transition: 0.2s; color : #000; margin : auto; } @keyframes roll { 30%, 60%, 90% { transform: scale(1) rotate(0deg); } 10%, 40%, 70% { transform: scale(1.11) rotate(-180deg); } 20%, 50%, 80% { transform: scale(0.9) rotate(-360deg); } }`; /*!***********************!*/ /**/modules["ui.css"] = /*** ./CSS/ui.css ***/ `.box { left : 50%; top : 50%; transform : translateX(-50%) translateY(-50%); min-width : 600px; min-height : 400px; padding : 0; border : 0; position : fixed; z-index : 11110; display : block; box-sizing : border-box; background : #fff; border-radius: 8px; box-shadow : 0 6px 12px 0 rgba(106, 115, 133, 22%); transition : transform 0.3s ease-in; line-height : 14px; font : 12px Helvetica Neue, Helvetica, Arial, Microsoft Yahei, Hiragino Sans GB, Heiti SC, WenQuanYi Micro Hei, sans-serif; } .tool { position : absolute; border-bottom-left-radius : 8px; border-bottom-right-radius: 8px; overflow : hidden; width : 100%; display : inline-flex; z-index : 1; align-items : center; justify-content : flex-end; pointer-events : none; } .tool div { border-radius : 50%; padding : 10px; transform : scale(0.8); pointer-events: visible; } .tool div:hover { background-color: rgba(0, 0, 0, 10%); } .content { position : relative; border-bottom-left-radius : 8px; border-bottom-right-radius: 8px; overflow : hidden; background-color : #fff; } .contain { padding-bottom : 15px; background-position: top center; background-size : contain; background-repeat : no-repeat; display : flex; align-items : flex-start; flex : 1; height : 385px; } .menu::-webkit-scrollbar, .item::-webkit-scrollbar { width : 0 !important; height: 0 !important; } .menu { flex : 1 1 0; flex-basis : calc(480px * 0.2); height : 100%; position : sticky; top : 0; display : flex; flex-direction: column; min-width : fit-content; overflow : auto; } .item { flex : 4 4 0; flex-basis: calc(480px * 0.8); height : 100%; box-sizing: border-box; display : block; margin : 0 auto; position : relative; overflow : auto; } .selected { color: rgb(51, 103, 214) !important; } .selected>.icon { fill: rgb(51, 103, 214) !important; }`; /*!***********************!*/ /**/modules["upList.css"] = /*** ./CSS/upList.css ***/ `.up-info-m .up-card-box { white-space: nowrap; overflow : auto; } .up-info-m .up-card { display : inline-block; margin-top: 10px; } .up-info-m .avatar img { cursor : pointer; width : 40px; height : 40px; border-radius: 50%; } .up-info-m .avatar { position: relative; } .up-info-m .avatar .info-tag { position : absolute; background : #fff; border : 1px solid #fb7299; border-radius: 2px; display : inline-block; font-size : 12px; color : #fb7299; padding : 0 3px; top : -10px; right : -10px; white-space : nowrap; } .up-info-m .avatar { width : 60px; height : 30px; display : -ms-flexbox; display : flex; -ms-flex-pack : center; justify-content: center; -ms-flex-align : start; align-items : flex-start; } .up-info-m .avatar .name-text { font-family : PingFangSC-Regular, sans-serif; line-height : 30px; color : #222; word-break : break-all; overflow : hidden; text-overflow : ellipsis; display : -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; white-space : nowrap; } .up-info-m .avatar .name-text.is-vip, .up-info-m .avatar .name-text:hover { color: #fb7299; } .up-info-m .title { display : block; font-size : 14px; margin-right: 80px; color : #525659; overflow : hidden; height : 24px; font-weight : 400; padding : 8px 0; }`; /*!***********************!*/ /**/modules["vanfont.css"] = /*** ./CSS/vanfont.css ***/ `@font-face { font-family: vanfont; src : url(//s1.hdslb.com/bfs/static/audio/medialist/asserts/iconfont.ae48418.eot); src : url(data:font/woff;base64,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) format("woff"), url(//s1.hdslb.com/bfs/static/audio/medialist/asserts/iconfont.6401a86.ttf) format("truetype"), url(//s1.hdslb.com/bfs/static/audio/medialist/asserts/iconfont.5899803.svg#iconfont) format("svg") } .vanfont { display : inline-block; font-style : normal; vertical-align : baseline; text-align : center; text-transform : none; line-height : 1; text-rendering : optimizeLegibility; -webkit-font-smoothing : antialiased; -moz-osx-font-smoothing: grayscale } .vanfont:before { display : block; font-family: vanfont !important } [class^=van-icon-] { display : inline-block; font-style : normal; vertical-align : baseline; text-align : center; text-transform : none; line-height : 1; text-rendering : optimizeLegibility; -webkit-font-smoothing : antialiased; -moz-osx-font-smoothing: grayscale } [class^=van-icon-]:before { display : block; font-family: vanfont !important } .van-icon-rotate:before { display : inline-block; animation: loadingCircle 1s linear infinite } .van-icon-error:before { content: "\\E62B" } .van-icon-serach:before { content: "\\E62F" } .van-icon-info:before { content: "\\E67D" } .van-icon-loading:before { content: "\\EEE3" } .van-icon-warning:before { content: "\\E664" } .van-icon-success:before { content: "\\E6F7" } .van-icon-jianpan:before { content: "\\E616" } .van-icon-lajitong:before { content: "\\E659" } .van-icon-lv0:before { content: "\\E6CB" } .van-icon-lv1:before { content: "\\E6CC" } .van-icon-lv2:before { content: "\\E6CD" } .van-icon-lv3:before { content: "\\E6CE" } .van-icon-lv4:before { content: "\\E6CF" } .van-icon-lv5:before { content: "\\E6D0" } .van-icon-lv6:before { content: "\\E6D1" } .van-icon-close:before { content: "\\E604" } .van-icon-rate-3:before { content: "\\E670" } .van-icon-rate-1:before { content: "\\E672" } .van-icon-rate-2:before { content: "\\E673" } .van-icon-fasong:before { content: "\\E666" } .van-icon-cai:before { content: "\\E638" } .van-icon-pinglun:before { content: "\\E639" } .van-icon-ding:before { content: "\\E63A" } .van-icon-guanbi:before { content: "\\E63C" } .van-icon-gengduo:before { content: "\\E63D" } .van-icon-biaoqing:before { content: "\\E63E" } .van-icon-videodetails_play:before { content: "\\E6E3" } .van-icon-videodetails_messag:before { content: "\\E6E5" } .van-icon-info_playnumber:before { content: "\\E6E6" } .van-icon-info_barragenumber:before { content: "\\E6E7" } .van-icon-info_rank:before { content: "\\E6E8" } .van-icon-info_prohibit:before { content: "\\E6E9" } .van-icon-general_moreactions:before { content: "\\E6EA" } .van-icon-general_pulldown_s:before { content: "\\E6EB" } .van-icon-general_pullup_s:before { content: "\\E6EC" } .van-icon-general_more:before { content: "\\E6ED" } .van-icon-general_close_s:before { content: "\\E6EE" } .van-icon-general_addto_s:before { content: "\\E6EF" } .van-icon-videodetails_collec:before { content: "\\E6E1" } .van-icon-videodetails_usemo:before { content: "\\E6E2" } .van-icon-videodetails_throw:before { content: "\\E6E4" } .van-icon-videodetails_like:before { content: "\\E6E0" } .van-icon-general_enter_s:before { content: "\\E6F0" } .van-icon-general_back_s:before { content: "\\E6F1" } .van-icon-floatwindow_custome:before { content: "\\E6F2" } .van-icon-share_weibo_default:before { content: "\\E71C" } .van-icon-share_tieba_default:before { content: "\\E71D" } .van-icon-share_wechat_default:before { content: "\\E721" } .van-icon-tuodong:before { content: "\\E665" } .van-icon-share_qq_default:before { content: "\\E71E" } .van-icon-share_news_default:before { content: "\\E71F" } .van-icon-share_qzone_default:before { content: "\\E720" } .van-icon-info_up:before { content: "\\E723" } .van-icon-Navbar_mobile:before { content: "\\E724" } .van-icon-Navbar_logo:before { content: "\\E725" } .van-icon-download:before { content: "\\E744" } .van-icon-general_viewlist:before { content: "\\E706" } .van-icon-general_viewmodule:before { content: "\\E707" } .van-icon-videodetails_share:before { content: "\\E70F" } .van-icon-general_upload:before { content: "\\E634" } .van-icon-general_search:before { content: "\\E635" } .van-icon-general_inplay:before { content: "\\E646" } .van-icon-info_warning:before { content: "\\E658" } .van-icon-gift:before { content: "\\E605" } .van-icon-notice:before { content: "\\E606" }`; /*!***********************!*/ /**/modules["anime.html"] = /*** ./HTML/anime.html ***/ ` 番剧 - 哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
`; /*!***********************!*/ /**/modules["av.html"] = /*** ./HTML/av.html ***/ ` 哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
`; /*!***********************!*/ /**/modules["bangumi.html"] = /*** ./HTML/bangumi.html ***/ ` 哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
`; /*!***********************!*/ /**/modules["index.html"] = /*** ./HTML/index.html ***/ ` 哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
`; /*!***********************!*/ /**/modules["player.html"] = /*** ./HTML/player.html ***/ ` player - bilibili.com
`; /*!***********************!*/ /**/modules["playlist.html"] = /*** ./HTML/playlist.html ***/ ` 哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
`; /*!***********************!*/ /**/modules["ranking.html"] = /*** ./HTML/ranking.html ***/ ` 热门视频排行榜 - 哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
`; /*!***********************!*/ /**/modules["read.html"] = /*** ./HTML/read.html ***/ ` 哔哩哔哩专栏
`; /*!***********************!*/ /**/modules["watchlater.html"] = /*** ./HTML/watchlater.html ***/ ` 哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
`; /*!***********************!*/ /**/modules["apply.json"] = /*** ./Json/apply.json ***/ { "closedCaption": "closedCaption.js", "localMedia": "localMedia.js", "segProgress": "segProgress.js", "aria2": "aria2.js", "download": "download.js", "ef2": "ef2.js", "jsonphook": "Node.js", "jsonphookasync": "Node.js", "scriptBlock": "Node.js", "scriptIntercept": "Node.js", "removeJsonphook": "Node.js", "xhrhook": "open.js", "xhrhookasync": "open.js", "removeXhrhook": "open.js", "allDanmaku": "allDanmaku.js", "danmaku": "danmaku.js", "element": "element.js", "clickRemove": "element.js", "EmbedPlayer": "EmbedPlayer.js", "fnval": "fnval.js", "mediaSession": "MediaMeta.js", "observerAddedNodes": "nodeObserver.js", "removeObserver": "nodeObserver.js", "rebuildPlayerurl": "rebuildPlayerurl.js", "rewrite": "rewrite.js", "switchVideo": "switchVideo.js", "url": "url.js", "urlInputCheck": "urlInputCheck.js", "abv": "abv.js", "base64": "Base64.js", "midcrc": "crc32.js", "crc32": "crc32.js", "bezier": "cubicBezier.js", "md5": "md5.js", "urlsign": "sign.js", "loadCommandDm": "commandDm.js", "initialStateOfAv": "initialStateOfAv.js", "initialStateOfBangumi": "initialStateOfBangumi.js" } /*!***********************!*/ /**/modules["mid.json"] = /*** ./Json/mid.json ***/ { "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 } /*!***********************!*/ /**/modules["protobuf.json"] = /*** ./Json/protobuf.json ***/ { "nested": { "bilibili": { "nested": { "DmWebViewReply": { "fields": { "state": { "type": "int32", "id": 1 }, "text": { "type": "string", "id": 2 }, "textSide": { "type": "string", "id": 3 }, "dmSge": { "type": "DmSegConfig", "id": 4 }, "flag": { "type": "DanmakuFlagConfig", "id": 5 }, "specialDms": { "rule": "repeated", "type": "string", "id": 6 }, "checkBox": { "type": "bool", "id": 7 }, "count": { "type": "int64", "id": 8 }, "commandDms": { "rule": "repeated", "type": "CommandDm", "id": 9 }, "dmSetting": { "type": "DanmuWebPlayerConfig", "id": 10 } } }, "CommandDm": { "fields": { "id": { "type": "int64", "id": 1 }, "oid": { "type": "int64", "id": 2 }, "mid": { "type": "int64", "id": 3 }, "command": { "type": "string", "id": 4 }, "content": { "type": "string", "id": 5 }, "progress": { "type": "int32", "id": 6 }, "ctime": { "type": "string", "id": 7 }, "mtime": { "type": "string", "id": 8 }, "extra": { "type": "string", "id": 9 }, "idStr": { "type": "string", "id": 10 } } }, "DmSegConfig": { "fields": { "pageSize": { "type": "int64", "id": 1 }, "total": { "type": "int64", "id": 2 } } }, "DanmakuFlagConfig": { "fields": { "recFlag": { "type": "int32", "id": 1 }, "recText": { "type": "string", "id": 2 }, "recSwitch": { "type": "int32", "id": 3 } } }, "DmSegMobileReply": { "fields": { "elems": { "rule": "repeated", "type": "DanmakuElem", "id": 1 } } }, "DanmakuElem": { "fields": { "id": { "type": "int64", "id": 1 }, "progress": { "type": "int32", "id": 2 }, "mode": { "type": "int32", "id": 3 }, "fontsize": { "type": "int32", "id": 4 }, "color": { "type": "uint32", "id": 5 }, "midHash": { "type": "string", "id": 6 }, "content": { "type": "string", "id": 7 }, "ctime": { "type": "int64", "id": 8 }, "weight": { "type": "int32", "id": 9 }, "action": { "type": "string", "id": 10 }, "pool": { "type": "int32", "id": 11 }, "idStr": { "type": "string", "id": 12 }, "attr": { "type": "int32", "id": 13 } } }, "DanmuWebPlayerConfig": { "fields": { "dmSwitch": { "type": "bool", "id": 1 }, "aiSwitch": { "type": "bool", "id": 2 }, "aiLevel": { "type": "int32", "id": 3 }, "blocktop": { "type": "bool", "id": 4 }, "blockscroll": { "type": "bool", "id": 5 }, "blockbottom": { "type": "bool", "id": 6 }, "blockcolor": { "type": "bool", "id": 7 }, "blockspecial": { "type": "bool", "id": 8 }, "preventshade": { "type": "bool", "id": 9 }, "dmask": { "type": "bool", "id": 10 }, "opacity": { "type": "float", "id": 11 }, "dmarea": { "type": "int32", "id": 12 }, "speedplus": { "type": "float", "id": 13 }, "fontsize": { "type": "float", "id": 14 }, "screensync": { "type": "bool", "id": 15 }, "speedsync": { "type": "bool", "id": 16 }, "fontfamily": { "type": "string", "id": 17 }, "bold": { "type": "bool", "id": 18 }, "fontborder": { "type": "int32", "id": 19 }, "drawType": { "type": "string", "id": 20 } } } } } } } /*!***********************!*/ /**/modules["videoSort.json"] = /*** ./Json/videoSort.json ***/ { "1": [ 1, "动画", "//www.bilibili.com/v/douga/" ], "3": [ 3, "音乐", "//www.bilibili.com/v/music/" ], "29": [ 3, "音乐现场", "//www.bilibili.com/v/music/live" ], "36": [ 36, "科技", "//www.bilibili.com/v/technology" ], "75": [ 217, "动物综合", "//www.bilibili.com/v/animal/animal_composite/" ], "76": [ 211, "美食制作", "//www.bilibili.com/v/food/make/" ], "86": [ 1, "特摄", "//www.bilibili.com/v/douga/" ], "95": [ 188, "数码", "//www.bilibili.com/v/digital/mobile/" ], "119": [ 119, "鬼畜", "//www.bilibili.com/v/kichiku/" ], "129": [ 129, "舞蹈", "//www.bilibili.com/v/dance" ], "155": [ 155, "时尚", "//www.bilibili.com/v/fashion" ], "157": [ 155, "美妆护肤", "//www.bilibili.com/v/fashion/makeup/" ], "158": [ 155, "穿搭", "//www.bilibili.com/v/fashion/clothing/" ], "159": [ 155, "时尚潮流", "//www.bilibili.com/v/fashion/trend/" ], "160": [ 160, "生活", "//www.bilibili.com/v/life" ], "163": [ 160, "家居房产", "//www.bilibili.com/v/life/home" ], "164": [ 234, "健身", "//www.bilibili.com/v/sports/aerobics" ], "168": [ 168, "国创", "//www.bilibili.com/guochuang" ], "176": [ 223, "汽车生活", "//www.bilibili.com/v/car/life/" ], "188": [ 188, "数码", "//www.bilibili.com/v/digital" ], "189": [ 188, "电脑装机", "//www.bilibili.com/v/digital/pc" ], "190": [ 188, "数码摄影", "//www.bilibili.com/v/digital/photography" ], "191": [ 188, "影音智能", "//www.bilibili.com/v/digital/intelligence_av" ], "192": [ 155, "风尚标", "//www.bilibili.com/v/fashion/trends" ], "193": [ 3, "MV", "//www.bilibili.com/v/music/mv" ], "194": [ 3, "电音", "//www.bilibili.com/v/music/electronic" ], "195": [ 168, "动态漫·广播剧", "//www.bilibili.com/v/guochuang/motioncomic" ], "198": [ 129, "街舞", "//www.bilibili.com/v/dance/hiphop" ], "199": [ 129, "明星舞蹈", "//www.bilibili.com/v/dance/star" ], "200": [ 129, "中国舞", "//www.bilibili.com/v/dance/china" ], "201": [ 36, "科学科普", "//www.bilibili.com/v/technology/science" ], "202": [ 202, "资讯", "//www.bilibili.com/v/information/" ], "203": [ 202, "热点", "//www.bilibili.com/v/information/hotspot/" ], "204": [ 202, "环球", "//www.bilibili.com/v/information/global/" ], "205": [ 202, "社会", "//www.bilibili.com/v/information/social/" ], "206": [ 202, "综合", "//www.bilibili.com/v/information/multiple/" ], "207": [ 36, "财经", "//www.bilibili.com/v/technology/finance" ], "208": [ 36, "校园学习", "//www.bilibili.com/v/technology/campus" ], "209": [ 36, "职业职场", "//www.bilibili.com/v/technology/career" ], "210": [ 1, "手办·模玩", "//www.bilibili.com/v/douga/garage_kit" ], "211": [ 211, "美食", "//www.bilibili.com/v/food" ], "212": [ 211, "美食侦探", "//www.bilibili.com/v/food/detective/" ], "213": [ 211, "美食测评", "//www.bilibili.com/v/food/measurement/" ], "214": [ 211, "田园美食", "//www.bilibili.com/v/food/rural/" ], "215": [ 211, "美食记录", "//www.bilibili.com/v/food/record/" ], "216": [ 119, "鬼畜剧场", "//www.bilibili.com/v/kichiku/theatre/" ], "217": [ 217, "动物圈", "//www.bilibili.com/v/animal" ], "218": [ 217, "喵星人", "//www.bilibili.com/v/animal/cat/" ], "219": [ 217, "汪星人", "//www.bilibili.com/v/animal/dog/" ], "220": [ 217, "大熊猫", "//www.bilibili.com/v/animal/panda/" ], "221": [ 217, "野生动物", "//www.bilibili.com/v/animal/wild_animal/" ], "222": [ 217, "爬宠", "//www.bilibili.com/v/animal/reptiles/" ], "223": [ 223, "汽车", "//www.bilibili.com/v/car" ], "224": [ 223, "汽车文化", "//www.bilibili.com/v/car/culture/" ], "225": [ 223, "汽车极客", "//www.bilibili.com/v/car/geek/" ], "226": [ 223, "智能出行", "//www.bilibili.com/v/car/smart/" ], "227": [ 223, "购车攻略", "//www.bilibili.com/v/car/strategy/" ], "228": [ 36, "人文历史", "//www.bilibili.com/v/knowledge/humanity_history/" ], "229": [ 36, "设计·创意", "//www.bilibili.com/v/knowledge/design/" ], "230": [ 188, "软件应用", "//www.bilibili.com/v/tech/application/" ], "231": [ 188, "计算机技术", "//www.bilibili.com/v/tech/computer_tech/" ], "232": [ 188, "工业·工程·机械", "//www.bilibili.com/v/tech/computer_tech/" ], "233": [ 188, "极客DIY", "//www.bilibili.com/v/tech/diy/" ], "234": [ 234, "运动", "//www.bilibili.com/v/sports" ], "235": [ 234, "篮球·足球", "//www.bilibili.com/v/sports/basketballfootball" ], "236": [ 234, "竞技体育", "//www.bilibili.com/v/sports/athletic" ], "237": [ 234, "运动文化", "//www.bilibili.com/v/sports/culture" ], "238": [ 234, "运动综合", "//www.bilibili.com/v/sports/comprehensive" ], "240": [ 223, "摩托车", "//www.bilibili.com/v/car/motorcycle" ] } /*!***********************!*/ /**/modules["main.js"] = /*** ./dist/main.js ***/ `(function () { /** * UI设置项注册栈 */ const SETTING = []; /** * UI子菜单栈 */ const MENU = {}; class Window { GM = GM; config = config; debug = debug; Format = Format; toast = toast; xhr = xhr; Name = GM.info.script.name; Virsion = GM.info.script.version; Handler = [GM.info.scriptHandler, GM.info.version].join(" "); uid = Number(this.getCookies().DedeUserID); static aids = {}; path = location.href.split("/"); constructor() { if (this.uid) { // 代理旧版退出登录页面 if (location.href.includes("bilibili.com/login?act=exit")) this.loginExit(document.referrer); // 修复动态时间线 let offset = this.getCookies()["bp_video_offset_" + this.uid]; offset && this.setCookie("bp_t_offset_" + this.uid, offset); } } importModule(name, args = {}) { if (!name) return Object.keys(modules).filter(p => typeof modules[p] === "string"); // 空调用返回所有可用模块 if (typeof modules[name] === "string") { // 有效调用 new Function("API", "GM", "config", "debug", "Format", "toast", "xhr", ...Object.keys(args), modules[name])(API, GM, config, debug, Format, toast, xhr, ...Object.keys(args).reduce((s, d) => { s.push(args[d]); return s; }, [])); } else toast.warning(\`模块\${name}并不存在!是不是拼写错了?\`); // 无效调用 } getModule = (key) => modules[key]; registerSetting(obj) { SETTING.push(obj); Window.modifyConfig(obj); } static modifyConfig(obj) { try { obj.value && !Reflect.has(config, obj.key) && (config[obj.key] = obj.value); obj.type == "sort" && obj.list && obj.list.forEach((d) => { this.modifyConfig(d); }); } catch (e) { debug.warn(\`UI设置项注册错误!\`, obj); } } registerMenu(obj) { MENU[obj.key] = obj; } changeSettingMode(mode) { const keys = Object.keys(mode); SETTING.forEach(d => { d.key && keys.includes(d.key) && (d.hidden = mode[d.key]); }); } getCookies() { return document.cookie.split('; ').reduce((s, d) => { let key = d.split('=')[0]; let val = d.split('=')[1]; s[key] = unescape(val); return s; }, {}); } setCookie(name, value, days = 365) { const exp = new Date(); exp.setTime(exp.getTime() + days * 24 * 60 * 60 * 1000); document.cookie = name + '=' + escape(value) + ';expires=' + exp.toUTCString() + '; path=/; domain=.bilibili.com'; } async loginExit(referer) { if (!this.uid) return toast.warning("本就未登录,无法退出登录!"); toast.warning("正在退出登录..."); let data = this.jsonCheck(await this.xhr({ url: "https://passport.bilibili.com/login/exit/v2", data: \`biliCSRF=\${this.getCookies().bili_jct}&gourl=\${encodeURIComponent(location.href)}\`, method: "POST", credentials: true })); if (data.status) { toast.success("退出登录!"); if (referer) return location.replace(referer); setTimeout(() => location.reload(), 1000); } } jsonCheck(data) { let result = typeof data === "string" ? JSON.parse(data) : data; if ("code" in result && result.code !== 0) { let msg = result.msg || result.message || ""; throw [result.code, msg]; } return result; } biliQuickLogin() { window.biliQuickLogin ? window.biliQuickLogin() : this.loadScript("//static.hdslb.com/account/bili_quick_login.js", () => this.biliQuickLogin()); } loadScript(src, onload) { const script = document.createElement("script"); script.type = "text/javascript"; script.src = src; script.addEventListener("load", () => { script.remove(); onload(); }); document.body.appendChild(script); } getTotalTop(node) { var sum = 0; do { sum += node.offsetTop; node = node.offsetParent; } while (node); return sum; } async saveAs(content, fileName, contentType = "text/plain") { const a = document.createElement("a"); const file = new Blob([content], { type: contentType }); a.href = URL.createObjectURL(file); a.download = fileName; a.addEventListener("load", () => URL.revokeObjectURL(a.href)); // document.body.appendChild(a); a.click(); } readAs(file, type = "string", encoding) { return new Promise((resolve, reject) => { const reader = new FileReader(); switch (type) { case "ArrayBuffer": reader.readAsArrayBuffer(file); break; case "DataURL": reader.readAsDataURL(file); break; case "string": reader.readAsText(file, encoding || 'utf-8'); break; } reader.onload = () => resolve(reader.result); reader.onerror = e => reject(e); }); } getUrlValue(name) { const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|\$)", "i"); const r = window.location.search.substr(1).match(reg); if (r != null) return decodeURIComponent(r[2]); return null; } async getAidInfo(aid) { if (!Window.aids[aid]) { const data = await xhr({ url: \`https://api.bilibili.com/x/web-interface/view/detail?aid=\${aid}\`, responseType: "json", credentials: true }); Window.aids[aid] = data.data; } return Window.aids[aid]; } strSize(str) { let size = 0; for (let i = 0; i < str.length; i++) { const code = str.charCodeAt(i); if (code <= 0x007f) size++; else if (code <= 0x07ff) size += 2; else if (code <= 0xffff) size += 3; else size += 4; } return size; } async addCss(txt, id, parrent) { if (!parrent && !document.head) { await new Promise(r => this.runWhile(() => document.body, r)); } parrent = parrent || document.head; const style = document.createElement("style"); style.setAttribute("type", "text/css"); id && !parrent.querySelector(\`#\${id}\`) && style.setAttribute("id", id); style.appendChild(document.createTextNode(txt)); parrent.appendChild(style); } addElement(tag, attribute, parrent, innerHTML, top, replaced) { let element = document.createElement(tag); attribute && (Object.entries(attribute).forEach(d => element.setAttribute(d[0], d[1]))); parrent = parrent || document.body; innerHTML && (element.innerHTML = innerHTML); replaced ? replaced.replaceWith(element) : top ? parrent.insertBefore(element, parrent.firstChild) : parrent.appendChild(element); return element; } runWhile(check, callback, delay = 100, stop = 180) { let timer = setInterval(() => { if (check()) { clearInterval(timer); callback(); } }, delay); stop && setTimeout(() => clearInterval(timer), stop * 1000); } bofqiMessage(msg, time = 3, callback, replace = true) { let node = document.querySelector(".bilibili-player-video-toast-bottom"); if (!node) { if (msg) { if (Array.isArray(msg)) return debug.log(...msg); return debug.log(msg); } return; } if (!msg) node.childNodes.forEach(d => d.remove()); const table = document.querySelector(".bilibili-player-video-toast-item.bilibili-player-video-toast-pay") || document.createElement("div"); table.setAttribute("class", "bilibili-player-video-toast-item bilibili-player-video-toast-pay"); const ele = document.createElement("div"); ele.setAttribute("class", "bilibili-player-video-toast-item-text"); table.appendChild(ele); msg = Array.isArray(msg) ? msg : [msg]; if (!msg[0]) return; replace && node.childNodes.forEach(d => d.remove()); ele.innerHTML = msg.reduce((s, d, i) => { if (d) { switch (i) { case 0: s += \`\${d}\`; break; case 1: s += \`\${d}\`; break; case 2: s += \`\${d}\`; break; } } return s; }, ''); node.appendChild(table); callback && (ele.style.cursor = "pointer") && (ele.onclick = () => callback()); (time !== 0) && setTimeout(() => { ele.remove(); !table.children[0] && table.remove(); }, time * 1000); } async alertMessage(text, title = this.Name) { return new Promise((r) => { const root = this.addElement("div"); const div = root.attachShadow({ mode: "closed" }); const table = this.addElement("div", { class: "table" }, div, \`
\${title}
\${text}
确认
取消
\`); this.addCss(this.getCss("alert.css", "button.css"), '', div); table.querySelectorAll(".button").forEach((d, i) => { i ? (d.onclick = () => { root.remove(), r(false); }) : (d.onclick = () => (root.remove(), r(true))); }); }); } getCss(...svg) { return svg.reduce((s, d) => { s += \`\\r\\n\${this.getModule(d)}\`; return s; }, ""); } } // 本变量需要提升 var API = new Proxy(new Window(), { get: (t, p) => { if (window[p] && typeof window[p] !== "function") return window[p]; // 代理函数以外的全局变量,aid关键参数以本方式初始化 if (t[p]) return t[p]; // 接口存在直接返回 if (typeof p === "string" && modules["apply.json"][p]) { // 接口不存在访问“按需加载”关系表 t.importModule(modules["apply.json"][p]); return t[p]; } return undefined; }, set: (t, p, v) => { if (window[p] && typeof window[p] !== "function" && window[p] != v) window[p] = v; // 同步函数以外的全局变量 else t[p] = v; // 同步接口 return true; } }); API.importModule("vector.js"); // 进入引导模块 window.top === window.self && API.runWhile(() => document.body, () => API.importModule("ui.js", { MENU, SETTING })); // 绘制设置UI })(); //# sourceURL=API://@Bilibili-Old/main.js`; /*!***********************!*/ /**/modules["vector.js"] = /*** ./dist/vector.js ***/ `try { const disable = sessionStorage.getItem("disable_rewrite"); if (disable) { setTimeout(() => toast.warning(disable), 1000); sessionStorage.removeItem("disable_rewrite"); } // 模块引导起点 config.developer && (window.API = API); // 开发者模式 API.importModule("parameterTrim.js"); // 网址及超链接清理 API.importModule("replyList.js"); // 回复翻页评论区及楼层号 config.logReport && API.importModule("logReport.js"); // 拦截B站日志上报 // 重写分别引导入口,专属对应页面的模块请转向对应引导模块 if (!disable) { if (config.av && /\\/video\\/[AaBb][Vv]/.test(location.href)) API.importModule("av.js"); if (config.bangumi && /\\/bangumi\\/play\\/(ss|ep)/.test(location.href)) API.importModule("bangumi.js"); if (config.watchlater && /\\/watchlater/.test(location.href)) API.importModule("watchlater.js"); if (config.player && /player\\./.test(location.href)) API.importModule("player.js"); if (/space\\.bilibili\\.com/.test(location.href)) API.importModule("space.js"); if (config.index && API.path[2] == 'www.bilibili.com' && (!API.path[3] || (API.path[3].startsWith('\\?') || API.path[3].startsWith('\\#') || API.path[3].startsWith('index.')))) API.importModule("index.js"); if (config.ranking && /\\/v\\/popular\\//.test(location.href)) API.importModule("ranking.js"); if (/live\\.bilibili\\.com/.test(location.href)) API.importModule("live.js"); if (config.anime && /\\/anime\\/?(\\?.+)?\$/.test(location.href)) API.importModule("anime.js"); if (API.path[2] == "message.bilibili.com") API.addCss(API.getModule("message.css")); if (window.self == window.top && API.path[2] == 'www.bilibili.com') document.domain = "bilibili.com"; if (location.href.includes("message.bilibili.com/pages/nav/index_new_sync")) API.addCss(API.getModule("imroot.css")); if (location.href.includes("www.bilibili.com/account/history")) API.importModule("history.js"); if (config.read && /\\/read\\/[Cc][Vv]/.test(location.href)) API.importModule("read.js"); if (config.player && /festival\\/202[1-2]bnj/.test(location.href)) API.importModule("bnj.js"); if ((config.medialist && /\\/medialist\\/play\\//.test(location.href) && !/watchlater/.test(location.href)) || /\\/playlist\\/video\\/pl/.test(location.href)) API.importModule("medialist.js"); } // 重写之后再引导的全局模块 API.importModule("infoNewNumber.js"); // 移除旧版顶栏失效资讯数据 config.protoDm && API.importModule("protoDm.js"); // 旧版播放器新版protobuf弹幕支持 API.importModule("playinfo.js"); // 视频源修复及记录 API.importModule("player-v2.js"); // 视频信息接口 API.importModule("automate.js"); // 自动化处理 config.videoLimit && API.importModule("videoLimit.js"); // 解锁视频限制 API.importModule("banner.js"); // 移植动态顶栏banner config.section && API.importModule("section.js"); // 还原旧版顶栏 config.danmakuHashId && API.path.name && API.importModule("danmakuHashId.js"); // 反查弹幕发送者 config.downloadContentmenu && API.importModule("rightKey.js"); // 下载右键菜单 API.importModule().forEach((d) => { d.includes("[run]") && API.importModule(d); }); // 自运行脚本 } catch (e) { toast.error(API.Name, e); } //# sourceURL=API://@Bilibili-Old/vector.js`; /*!***********************!*/ /**/modules["[run]proxyBigVip.js"] = /*** ./dist/[run]proxyBigVip.js ***/ `{ const Backup = {}; API.registerSetting({ key: "proxyBigVip", sort: "player", label: "代理大会员", sub: "借助第三方服务器", type: "sort", list: [{ type: "switch", key: "bigvip", value: true, sort: "player", label: "代理开关" }, { key: "proxyServerVision", sort: "player", label: "接口版本", type: "input", input: { type: "text" }, value: "0.1.8" }, { key: "proxyBigVipFlesh", sort: "player", label: "刷新签名", type: "action", title: "刷新", disabled: 0, action: () => { sign().then(d => d ? toast.success("已刷新签名!") : toast.error("刷新失败!您是否已登录?")); } }] }); async function sign() { if (!API.uid) return; const cookies = (await GM.cookie("list", {})).reduce((s, d) => { Reflect.set(s, d.name, encodeURIComponent(d.value)); return s; }, {}); const data = API.base64.encode(JSON.stringify({ cookie: Object.entries(cookies).reduce((s, d) => { s.push(\`\${d[0]}=\${d[1]}\`); return s; }, []).join(";"), csrf: cookies.bili_jct, level: 6, mid: cookies.DedeUserID, ua: navigator.userAgent, vip: 0 })); GM.setValue("bigvipSign", data); return data; } class HookTimeOut { hook; constructor() { this.hook = setTimeout; window.setTimeout = (...args) => { if (args[1] && args[1] == 1500 && args[0] && args[0].toString() == "function(){f.cz()}") { toast.warning("禁用播放器强制初始化!", ...args); return Number.MIN_VALUE; } return this.hook.call(window, ...args); }; } relese() { window.setTimeout = this.hook; } } if (config.bigvip) { API.xhrhook("season/user/status?", undefined, obj => { const response = API.jsonCheck(obj.responseText); if (response && !response.result.pay && !(response.result.real_price > 0)) { response.result.pay = 1; obj.response = obj.responseText = JSON.stringify(response); } }, false); API.xhrhookasync("/playurl?", args => { const obj = Format.urlObj(args[1]); return API.vipCid && obj.cid && API.vipCid.includes(Number(obj.cid)); }, async (args) => { const hookTimeout = new HookTimeOut(); let response; const obj = Format.urlObj(args[1]); try { toast.info("尝试代理大会员~"); response = Backup[obj.cid] || API.jsonCheck(await xhr.GM({ url: Format.objUrl("http://123.207.22.95/bz/ajax.php", { act: "bvlink", ...obj, version: config.proxyServerVision, sign: GM.getValue("bigvipSign") || await sign() }), responseType: "json" })); API.__playinfo__ = response; Backup[obj.cid] = response; toast.success(\`解除大会员限制!aid=\${API.aid}, cid=\${API.cid}\`); } catch (e) { toast.error("代理大会员失败!", e); response = { "code": -404, "message": e, "data": null }; } hookTimeout.relese(); return { response: JSON.stringify(response), responseText: JSON.stringify(response) }; }, false); } } //# sourceURL=API://@Bilibili-Old/[run]proxyBigVip.js`; /*!***********************!*/ /**/modules["accesskey.js"] = /*** ./dist/do/accesskey.js ***/ `class Accesskey { access_key = GM.getValue("access_key", ""); access_date = GM.getValue("access_date", 0); box; enable; disable; foot; num = 0; /** * 创建移动端鉴权获取面板 */ constructor() { this.box = API.element.popupbox({ maxWidth: "360px", maxHeight: "300px" }); API.addElement("div", { style: 'text-align: center;font-size: 16px;font-weight: bold;margin-bottom: 10px;' }, this.box, \`账户授权\`); API.addElement("div", { style: 'margin-bottom: 10px;' }, this.box, \`
授权代理服务器使用您的账户权限,以在限制视频等操作中继承您的大会员权益。 这意味着第三方拥有您的账户访问权限,请充分考虑其中干系后谨慎操作! 如果只是为了解除视频限制,以“游客”身份也一样可以获取到最高1080P的视频源,而且一般不会有大会员专享限制。
※ 鉴权有效期一般在一个月左右,若是失效需要手动重新授权,脚本不会代为检查。
\`); this.box.appendChild(API.element.hr()); const body = API.addElement("div", { style: "display: flex;align-items: center;justify-content: space-around;margin-bottom: 10px;" }, this.box); this.enable = body.appendChild(API.element.button(() => { this.access(); }, "开始授权", 3)); this.disable = body.appendChild(API.element.button(() => { this.abort(); }, "取消授权", 10)); this.box.appendChild(API.element.hr()); this.foot = API.addElement("div", { style: "display: flex;align-items: center;justify-content: space-around;" }, this.box); this.flesh(); } /** * 重新获取鉴权按钮 */ flesh() { if (this.access_key) { const temp = API.element.button(() => { this.access(); }, "重新授权", 3); this.enable.replaceWith(temp); this.disable.style.display = "block"; this.enable = temp; this.foot.innerHTML = \`
授权状态:已授权
授权日期:\${Format.timeFormat(this.access_date, true)}
\`; } else { const temp = API.element.button(() => { this.access(); }, "开始授权", 3); this.enable.replaceWith(temp); this.enable = temp; this.disable.style.display = "none"; this.foot.innerHTML = \`
授权状态:未授权
\`; } } /** * 请求移动端鉴权 */ async access() { if (!API.uid) return (toast.warning("请先登录!"), API.biliQuickLogin()); toast("您正在进行账户授权操作,请稍候~"); let data = await xhr.GM({ url: API.urlsign("https://passport.bilibili.com/login/app/third?api=https%3A%2F%2Fwww.mcbbs.net%2Ftemplate%2Fmcbbs%2Fimage%2Fspecial_photo_bg.png", undefined, 3), responseType: "json" }); data = await new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: "GET", url: data.data.confirm_uri, onload: (xhr) => resolve(xhr.finalUrl), onerror: (xhr) => reject(xhr), }); }); data = Format.urlObj(data); await new Promise((resolve, reject) => { this.pluslogin(data, resolve, reject); }); this.access_key = data.access_key; this.access_date = new Date().getTime(); GM.setValue("access_key", this.access_key); GM.setValue("access_date", this.access_date); toast.success("账户授权成功!"); this.flesh(); } /** * 取消移动端鉴权并清除一切数据 */ async abort() { toast("正在取消账户授权,请稍候~"); this.access_key = ""; this.access_date = 0; GM.deleteValue("access_key"); GM.deleteValue("access_date"); await new Promise((resolve) => { const iframe = document.createElement("iframe"); iframe.setAttribute("style", "width: 0px;height: 0px;"); iframe.src = "https://www.biliplus.com/login?act=logout"; iframe.onload = () => { iframe.remove(); resolve(); }; iframe.onerror = () => { iframe.remove(); resolve(); }; document.body.appendChild(iframe); }); toast.success("已取消账户授权并销毁痕迹!"); this.flesh(); } /** * 登录到biliplus,用于解除视频限制 */ pluslogin(data, resolve, reject) { this.num++; const iframe = document.createElement("iframe"); iframe.setAttribute("style", "width: 0px;height: 0px;"); iframe.src = Format.objUrl("https://www.biliplus.com/login", data); iframe.onload = () => { iframe.remove(); resolve(); }; iframe.onerror = ev => { if (this.num < 4) { toast.error("授权出错!将在3秒后重试~", ev); setTimeout(() => this.pluslogin(data, resolve, reject), 3e3); } else { toast.error("重试终止!请参考控制台报错信息~"); reject(ev); } }; document.body.appendChild(iframe); } } new Accesskey(); //# sourceURL=API://@Bilibili-Old/do/accesskey.js`; /*!***********************!*/ /**/modules["automate.js"] = /*** ./dist/do/automate.js ***/ `{ function bofqiToView() { let str = [".bangumi_player", "#bofqi", "#bilibiliPlayer"]; let node = str.reduce((s, d) => { s = s || document.querySelector(d); return s; }, document.querySelector("#__bofqi")); node && node.scrollIntoView({ behavior: 'smooth', block: 'center' }); } // 播放器自动化操作 API.switchVideo(() => { config.danmakuFirst && document.querySelectorAll(".bilibili-player-filter-btn")[1].click(); setTimeout(() => { config.showBofqi && bofqiToView(); config.screenWide && document.querySelector(".bilibili-player-iconfont.bilibili-player-iconfont-widescreen.icon-24wideoff") && document.querySelector(".bilibili-player-video-btn.bilibili-player-video-btn-widescreen").click(); config.webFullScreen && document.querySelector(".bilibili-player-iconfont.bilibili-player-iconfont-web-fullscreen.icon-24webfull.player-tooltips-trigger") && document.querySelector(".bilibili-player-video-web-fullscreen").click(); if (config.noDanmaku && !document.querySelector(".bilibili-player-video-btn.bilibili-player-video-btn-danmaku.video-state-danmaku-off")) { if (document.querySelector(".bilibili-player-video-btn.bilibili-player-video-btn-danmaku")) { document.querySelector(".bilibili-player-video-btn.bilibili-player-video-btn-danmaku").click(); // 自动关闭弹幕 } } }, 500); config.autoPlay && setTimeout(() => { window.player && window.player.play && window.player.play(); }, 1000); }); // 播放本地媒体按钮 API.path.name && API.observerAddedNodes(e => { if (e.className && /bilibili-player-danmaku-setting-lite-panel/.test(e.className)) { API.runWhile(() => document.querySelector(".bilibili-player-setting-dmask-wrap"), () => { const node = document.querySelector(".bilibili-player-setting-dmask-wrap").parentElement; const lebel = API.addElement("label", { class: "bpui-checkbox-text", style: "cursor: pointer;display: inline-table;" }, node, "本地文件"); const input = API.addElement("input", { type: "file", accept: ".mp4,.xml,.json", multiple: "multiple", style: "width: 0;" }, lebel); input.onchange = () => { (!window.player?.setDanmaku) && toast.warning("内部组件丢失,无法载入弹幕文件!"); new API.localMedia(input.files); }; }); } }); // 修复顶栏分区数据 API.runWhile(() => document.querySelector(".bili-header-m"), () => { try { let node = document.querySelector(".bili-header-m").getElementsByClassName('nav-name'); if (node[0]) { for (let i = 0; i < node.length; i++) { if (node[i].textContent == "科技") { node[i].textContent = "知识"; node[i].parentNode.href = "//www.bilibili.com/v/knowledge/"; node[i].parentNode.parentNode.children[1].innerHTML = \`
  • 科学科普
  • 社科·法律·心理
  • 人文历史
  • 财经商业
  • 校园学习
  • 职业职场
  • 设计·创意
  • 野生技能协会
  • \`; } if (node[i].textContent == "数码") { node[i].textContent = "科技"; node[i].parentNode.href = "//www.bilibili.com/v/tech/"; node[i].parentNode.parentNode.children[1].innerHTML = \`
  • 数码
  • 软件应用
  • 计算机技术
  • 工业·工程·机械
  • 极客DIY
  • \`; } if (node[i].textContent == "时尚") { node[i].parentNode.parentNode.children[1].innerHTML = \`
  • 美妆护肤
  • 穿搭
  • 时尚潮流
  • \`; } if (node[i].textContent == "广告") { node[i].textContent = "资讯"; node[i].parentNode.href = "//www.bilibili.com/v/information/"; node[i].parentNode.parentNode.children[1].innerHTML = \`
  • 热点
  • 环球
  • 社会
  • 综合
  • \`; } if (node[i].textContent == "生活") { node[i].parentNode.parentNode.children[1].children[2].remove(); // 移除美食圈 node[i].parentNode.parentNode.children[1].children[2].remove(); // 移除美食圈 node[i].parentNode.parentNode.children[1].children[5].remove(); // 移除其他 node[i].parentNode.parentNode.children[1].children[4].children[0].href = "//www.bilibili.com/v/sports"; // 修复运动区链接 } if (node[i].textContent == "娱乐") node[i].parentNode.parentNode.children[1].lastChild.remove(); } } } catch (e) { debug.error("automate.js", e); } }); config.heartbeat && API.xhrhook(['api.bilibili.com/x/report/web/heartbeat'], function (args) { args[1] = args[1].replace('api.bilibili.com/x/report/web/heartbeat', 'api.bilibili.com/x/click-interface/web/heartbeat'); }, undefined, false); config.unloginPopover && !API.uid && API.runWhile(() => document.querySelector(".lt-row"), () => document.querySelector(".lt-row").remove()); // 移除登录提示弹窗 config.unloginPopover && !API.uid && API.runWhile(() => document.querySelector(".unlogin-popover"), () => document.querySelector(".unlogin-popover").remove()); // 移除登录提示弹窗 } //# sourceURL=API://@Bilibili-Old/do/automate.js`; /*!***********************!*/ /**/modules["banner.js"] = /*** ./dist/do/banner.js ***/ `{ class Animate { static record = {}; static rid = this.resourceId(); static locs = [1576, 1612, 1580, 1920, 1584, 1588, 1592, 3129, 1600, 1608, 1604, 1596, 2210, 1634, 142]; /** * 有在启用了动画banner的配置,且浏览器支持css filter时才加载动画banner的图片资源 * safari浏览器在mac屏幕上模糊效果有性能问题,不开启 */ animatedBannerSupport = typeof CSS !== 'undefined' && CSS.supports && CSS.supports('filter: blur(1px)') && !/^((?!chrome|android).)*safari/i.test(navigator.userAgent); layerConfig; resources = []; /** * container 元素上有其他元素,需使用全局事件判断鼠标位置 */ entered = false; extensions = []; handleMouseLeave; handleMouseMove; handleResize; constructor(v) { if (this.animatedBannerSupport) this.mounted(v); API.addCss(API.getModule("animated-banner.css"), "animated-banner"); if (v.is_split_layer !== 0) { API.addCss(".blur-bg {display:none}"); } else API.addCss(".blur-bg {background:none !important;-webkit-backdrop-filter: blur(4px);backdrop-filter: blur(4px)}"); } /** * 根据页面返回resourceId * @returns resourceId */ static resourceId() { if (location.href.includes("v/douga")) return 1576; if (location.href.includes("/anime")) return 1612; if (location.href.includes("v/music")) return 1580; if (location.href.includes("/guochuang")) return 1920; if (location.href.includes("v/dance")) return 1584; if (location.href.includes("v/game")) return 1588; if (location.href.includes("v/knowledge")) return 1592; if (location.href.includes("v/tech")) return 3129; if (location.href.includes("v/life")) return 1600; if (location.href.includes("v/kichiku")) return 1608; if (location.href.includes("v/fashion")) return 1604; if (location.href.includes("v/ent")) return 1596; if (location.href.includes("v/cinephile")) return 2210; if (location.href.includes("/cinema")) return 1634; return 142; } async mounted(v) { this.layerConfig = JSON.parse(v.split_layer); if (!this.layerConfig.layers) return; try { if ("extensions" in this.layerConfig && "time" in this.layerConfig.extensions) { let time, now = (Date.now() - (new Date).setHours(0, 0, 0, 0)) / 1e3; let timeCode = Object.keys(this.layerConfig.extensions.time).sort((a, b) => parseInt(a) - parseInt(b)); for (let t of timeCode) { if (parseInt(t) < now) time = parseInt(t); else break; } let timelayers = this.layerConfig.extensions.time[time]; this.layerConfig.layers = timelayers[Math.floor(Math.random() * timelayers.length)].layers; } await Promise.all(this.layerConfig.layers.map(async (v, index) => { return Promise.all(v.resources.map(async (i) => { if (/\\.(webm|mp4)\$/.test(i.src)) { const res = await xhr({ url: i.src, responseType: "blob" }); const url = URL.createObjectURL(res); const video = document.createElement('video'); video.muted = true; // video.autoplay = true video.loop = true; video.src = url; video.playsInline = true; video.style.objectFit = 'cover'; // 元素尺寸大于视频实际尺寸时放大 this.resources[index] = video; // 视频需要添加到dom树才能获取宽高 video.width = 0; video.height = 0; document.body.appendChild(video); await new Promise(resolve => { const onMetaLoad = () => { resolve(true); video.removeEventListener('loadedmetadata', onMetaLoad); }; video.addEventListener('loadedmetadata', onMetaLoad); }); } else { const img = document.createElement('img'); img.src = i.src; await new Promise(resolve => img.onload = resolve); this.resources[index] = img; } })); })); } catch (e) { debug.error('load animated banner images error', e); return; } let container = document.querySelector("#banner_link"); if (!container) { container = document.querySelector(".h-center"); if (!container) return this.resources.forEach(d => d.remove()); container.parentElement.removeAttribute("style"); container.style.width = "100%"; container.style.top = "-42px"; container.style.marginBottom = "-42px"; container.innerHTML = ""; document.querySelector(".b-header-mask-wrp").remove(); } ; container.classList.add("animated-banner"); let containerHeight = container.clientHeight; let containerWidth = container.clientWidth; let containerScale = (containerHeight + 10) / 155; // 初始化资源尺寸 this.layerConfig.layers.forEach(v => { v._initState = { scale: 1, rotate: v.rotate?.initial || 0, translate: v.translate?.initial || [0, 0], blur: v.blur?.initial || 0, opacity: v.opacity?.initial === undefined ? 1 : v.opacity.initial, }; v.resources.forEach((i, index) => { const el = this.resources[index]; if (el.tagName === 'VIDEO') { if (el.parentNode) { el.parentNode.removeChild(el); } el.dataset.height = el.videoHeight; el.dataset.width = el.videoWidth; } else { el.dataset.height = el.naturalHeight; el.dataset.width = el.naturalWidth; } const initial = v.scale?.initial === undefined ? 1 : v.scale?.initial; el.height = el.dataset.height * containerScale * initial; el.width = el.dataset.width * containerScale * initial; }); }); // 初始化图层 const layers = this.layerConfig.layers.map(v => { const layer = document.createElement('div'); layer.classList.add('layer'); container.appendChild(layer); return layer; }); let displace = 0; let enterX = 0; let raf = 0; const curveParameterToFunc = (param) => { const o = API.bezier(...param); return v => v > 0 ? o(v) : -o(-v); }; let lastDisplace = NaN; // 根据鼠标位置改变状态 const af = t => { try { if (lastDisplace === displace) { return; } lastDisplace = displace; layers.map((layer, i) => { const v = this.layerConfig.layers[i]; const a = layer.firstChild; if (!a) { return; } const transform = { scale: v._initState.scale, rotate: v._initState.rotate, translate: v._initState.translate, }; if (v.scale) { const x = v.scale.offset || 0; const itp = v.scale.offsetCurve ? curveParameterToFunc(v.scale.offsetCurve) : (x => x); const offset = x * itp(displace); transform.scale = v._initState.scale + offset; } if (v.rotate) { const x = v.rotate.offset || 0; const itp = v.rotate.offsetCurve ? curveParameterToFunc(v.rotate.offsetCurve) : (x => x); const offset = x * itp(displace); transform.rotate = v._initState.rotate + offset; } if (v.translate) { const x = v.translate.offset || [0, 0]; const itp = v.translate.offsetCurve ? curveParameterToFunc(v.translate.offsetCurve) : (x => x); const offset = x.map(v => itp(displace) * v); const translate = v._initState.translate.map((x, i) => (x + offset[i]) * containerScale * (v.scale?.initial || 1)); transform.translate = translate; } a.style.transform = \`scale(\${transform.scale})\` + \`translate(\${transform.translate[0]}px, \${transform.translate[1]}px)\` + \`rotate(\${transform.rotate}deg)\`; if (v.blur) { const x = v.blur.offset || 0; const itp = v.blur.offsetCurve ? curveParameterToFunc(v.blur.offsetCurve) : (x => x); const blurOffset = x * itp(displace); let res = 0; if (!v.blur.wrap || v.blur.wrap === 'clamp') { res = Math.max(0, v._initState.blur + blurOffset); } else if (v.blur.wrap === 'alternate') { res = Math.abs(v._initState.blur + blurOffset); } a.style.filter = res < 1e-4 ? '' : \`blur(\${res}px)\`; } if (v.opacity) { const x = v.opacity.offset || 0; const itp = v.opacity.offsetCurve ? curveParameterToFunc(v.opacity.offsetCurve) : (x => x); const opacityOffset = x * itp(displace); const initial = v._initState.opacity; if (!v.opacity.wrap || v.opacity.wrap === 'clamp') { a.style.opacity = Math.max(0, Math.min(1, initial + opacityOffset)); } else if (v.opacity.wrap === 'alternate') { const x = initial + opacityOffset; let y = Math.abs(x % 1); if (Math.abs(x % 2) >= 1) { y = 1 - y; } a.style.opacity = y; } } }); } catch (e) { debug.error(e); } }; // 初始化图层内图片和帧动画 this.layerConfig.layers.map((v, i) => { const a = this.resources[i]; layers[i].appendChild(a); if (a.tagName === 'VIDEO') { a.play(); } requestAnimationFrame(af); }); const handleLeave = () => { const now = performance.now(); const timeout = 200; const tempDisplace = displace; cancelAnimationFrame(raf); const leaveAF = t => { if (t - now < timeout) { displace = tempDisplace * (1 - (t - now) / 200); af(t); requestAnimationFrame(leaveAF); } else { displace = 0; af(t); } }; raf = requestAnimationFrame(leaveAF); }; this.handleMouseLeave = e => { this.entered = false; handleLeave(); }; this.handleMouseMove = e => { const offsetY = document.documentElement.scrollTop + e.clientY; if (offsetY < containerHeight) { if (!this.entered) { this.entered = true; enterX = e.clientX; } displace = (e.clientX - enterX) / containerWidth; cancelAnimationFrame(raf); raf = requestAnimationFrame(af); } else { if (this.entered) { this.entered = false; handleLeave(); } } this.extensions.map(v => v.handleMouseMove?.({ e, displace })); }; this.handleResize = e => { containerHeight = container.clientHeight; containerWidth = container.clientWidth; containerScale = containerHeight / 155; this.layerConfig.layers.forEach(lc => { lc.resources.forEach((d, i) => { const el = this.resources[i]; el.height = el.dataset.height * containerScale * (lc.scale?.initial || 1); el.width = el.dataset.width * containerScale * (lc.scale?.initial || 1); }); }); cancelAnimationFrame(raf); raf = requestAnimationFrame(t => { af(t); }); this.extensions.map(v => v.handleResize?.(e)); }; document.addEventListener('mouseleave', this.handleMouseLeave); window.addEventListener('mousemove', this.handleMouseMove); window.addEventListener('resize', this.handleResize); } } config.bannerGif && API.jsonphook("api.bilibili.com/x/web-interface/index/icon", undefined, response => { response.data = Format.randomArray(JSON.parse(GM.getResourceText("index-icon.json")).fix, 1)[0]; return response; }, false); API.jsonphookasync("api.bilibili.com/x/web-show/res/loc", undefined, async (url) => { const obj = Format.urlObj(url); obj.callback = undefined; let loc = Animate.record[url]; let header = Animate.record[Animate.rid]; let rqs; if (!loc || !header) { rqs = await Promise.all([ xhr.get(Format.objUrl(url, obj), { responseType: "json" }), xhr.get(\`https://api.bilibili.com/x/web-show/page/header?resource_id=\${Animate.rid}\`, { responseType: "json" }) ]); loc = Animate.record[url] = rqs[0]; header = Animate.record[Animate.rid] = rqs[1]; } // document.querySelector("#banner_link").style.backgroundImage = \`url("\${header.data.pic}");\`; loc.data && Animate.locs.forEach(d => { loc.data[d] && (loc.data[d][0].pic = (header && header.data.pic) || "//i0.hdslb.com/bfs/activity-plat/static/20171220/68a052f664e8414bb594f9b00b176599/images/90w1lpp6ry.png", loc.data[d][0].litpic = (header && header.data.litpic), loc.data[d][0].url = (header && header.data.url) || "", loc.data[d][0].title = (header && header.data.name) || ""); if (url.includes("loc?") && obj.id == String(d)) { loc.data[0].pic = (header && header.data.pic) || "//i0.hdslb.com/bfs/activity-plat/static/20171220/68a052f664e8414bb594f9b00b176599/images/90w1lpp6ry.png"; loc.data[0].litpic = (header && header.data.litpic) || ""; loc.data[0].url = (header && header.data.url) || ""; loc.data[0].title = (header && header.data.name) || ""; } }); setTimeout(() => new Animate(header.data)); return loc; }, false); } //# sourceURL=API://@Bilibili-Old/do/banner.js`; /*!***********************!*/ /**/modules["closedCaption.js"] = /*** ./dist/do/closedCaption.js ***/ `class ClosedCaption { element = {}; // 节点集合 data = {}; // 字幕缓存 resizeRate = 100; // 字幕大小倍率 subtitle = []; // 字幕栈 ON = \`\`; OFF = \`\`; color = [ { value: '16777215', content: '白色' }, { value: '16007990', content: '红色' }, { value: '10233776', content: '紫色' }, { value: '6765239', content: '深紫色' }, { value: '4149685', content: '靛青色' }, { value: '2201331', content: '蓝色' }, { value: '240116', content: '亮蓝色' } ]; position = [ { value: 'bl', content: '左下角' }, { value: 'bc', content: '底部居中' }, { value: 'br', content: '右下角' }, { value: 'tl', content: '左上角' }, { value: 'tc', content: '顶部居中' }, { value: 'tr', content: '右上角' } ]; shadow = [ { value: '0', content: '无描边', style: '' }, { value: '1', content: '重墨', style: \`text-shadow: #000 1px 0px 1px, #000 0px 1px 1px, #000 0px -1px 1px,#000 -1px 0px 1px;\` }, { value: '2', content: '描边', style: \`text-shadow: #000 0px 0px 1px, #000 0px 0px 1px, #000 0px 0px 1px;\` }, { value: '3', content: '45°投影', style: \`text-shadow: #000 1px 1px 2px, #000 0px 0px 1px;\` } ]; setting; subtitlePrefer; // 首选语言 isON = false; // 是否启用 caption; // 当前字幕 contain; captions; // 字幕集 text; constructor() { this.setting = GM.getValue("subtitle", { backgroundopacity: 0.5, color: 16777215, fontsize: 1, isclosed: false, scale: true, shadow: "0", position: 'bc' }); this.subtitlePrefer = GM.getValue("subtitlePrefer"); // 默认语言 } /** * 绘制字幕面板 */ initUI() { this.element.node = document.createElement("div"); this.element.node.setAttribute("class", "bilibili-player-video-btn"); this.element.node.setAttribute("id", "bilibili-player-subtitle-btn"); this.element.node.setAttribute("style", "display: block;"); this.element.span = API.addElement("span", {}, this.element.node); this.element.span.innerHTML = this.ON; this.isON = true; this.element.span.onclick = () => { if (this.isON) this.iconSwitch(); else this.iconSwitch(this.caption); }; this.element.table = API.addElement("div", { id: "subtitle-setting-panel", style: "position: absolute; bottom: 28px; right: 30px; background: white; border-radius: 4px; text-align: left; padding: 13px; display: none; cursor: default;" }, this.element.node); this.language(); this.fontsize(); this.fontcolor(); this.fontshadow(); this.fontposition(); this.fontopacrity(); API.addCss(API.getModule("closedCaption.css"), "caption"); this.changeResize(); this.changePosition(); } /** * 切换字幕样式 */ changeStyle() { document.querySelector("#caption-style")?.remove(); API.addCss(\`span.subtitle-item-background{opacity: \${this.setting.backgroundopacity};} span.subtitle-item-text {color:#\${("000000" + this.setting.color.toString(16)).slice(-6)};} span.subtitle-item {font-size: \${this.setting.fontsize * this.resizeRate}%;line-height: 110%;} span.subtitle-item {\${this.shadow[this.setting.shadow].style}}\`, "caption-style"); GM.setValue("subtitle", this.setting); } /** * 切换字幕大小 */ changeResize() { this.resizeRate = this.setting.scale ? window.player.getWidth() / 1280 * 100 : 100; this.changeStyle(); } /** * 切换字幕位置 */ changePosition() { this.contain = document.querySelector(".bilibili-player-video-subtitle>div"); this.contain.className = 'subtitle-position subtitle-position-' + (this.setting.position || 'bc'); this.contain.style = ''; GM.setValue("subtitle", this.setting); } /** * 字幕图标切换 * @param caption */ iconSwitch(caption) { if (caption) { this.isON = true; this.element.span.innerHTML = this.ON; this.setCaption(caption); this.text.innerHTML = caption.lan_doc; this.element.language.children[2].disabled = false; } else { this.isON = false; this.element.span.innerHTML = this.OFF; this.setCaption(); this.text.innerHTML = "关闭"; this.element.language.children[2].disabled = true; } } /** * 字幕选择 */ language() { this.element.language = API.addElement("div", {}, this.element.table); this.element.language.innerHTML = \`
    字幕
    关闭
    • 关闭
    添加字幕\`; let list = this.element.language.children[1].children[2]; this.text = this.element.language.children[1].children[0]; // this.element.language.children[2].onclick = () => { // API.importModule("download"); // API.config.reset.dlother = 1; // 开启其他下载 // API.download(); // 拉起下载面板 // } list.children[0].onclick = () => { this.text.innerHTML = "关闭"; this.setCaption(); }; this.text.innerHTML = this.caption.lan_doc; this.captions = this.captions.reverse(); this.captions.forEach((d) => { let temp = API.addElement("div", { class: "bpui-selectmenu-list-row", "data-value": d.lan }, list, d.lan_doc, true); temp.onclick = () => { this.text.innerHTML = d.lan_doc; this.iconSwitch(d); GM.setValue("subtitlePrefer", this.subtitlePrefer = d.lan); }; }); } /** * 字幕大小 */ fontsize() { this.element.fontsize = API.addElement("div", {}, this.element.table); this.element.fontsize.innerHTML = \`
    字体大小
    \`; this.element.fontsize.children[1].value = this.setting.fontsize == 0.6 ? 0 : this.setting.fontsize == 0.8 ? 25 : this.setting.fontsize == 1.3 ? 75 : this.setting.fontsize == 1.6 ? 100 : 50; this.element.fontsize.children[1].oninput = (e) => { const v = e.target.value / 25; this.setting.fontsize = v > 2 ? (v - 2) * 0.3 + 1 : v * 0.2 + 0.6; this.changeStyle(); }; this.element.fontsize.children[2].checked = this.setting.scale; this.element.fontsize.children[2].onchange = (e) => this.changeResize(this.setting.scale = e.target.checked); } /** * 字幕颜色 */ fontcolor() { this.element.fontcolor = API.addElement("div", {}, this.element.table); this.element.fontcolor.innerHTML = \`字幕颜色
    白色
      \`; this.color.forEach(d => { if (d.value == this.setting.color) this.element.fontcolor.children[1].children[0].innerHTML = d.content; let temp = API.addElement("li", { class: "bpui-selectmenu-list-row", "data-value": d.value }, this.element.fontcolor.children[1].children[2]); temp.innerHTML = d.content; temp.onclick = () => { this.element.fontcolor.children[1].children[0].innerHTML = d.content; this.changeStyle(this.setting.color = parseInt(d.value)); }; }); } /** * 字幕阴影 */ fontshadow() { this.element.fontshadow = API.addElement("div", {}, this.element.table); this.element.fontshadow.innerHTML = \`字幕描边
      无描边
        \`; this.shadow.forEach(d => { if (d.value == this.setting.shadow) this.element.fontshadow.children[1].children[0].innerHTML = d.content; let temp = API.addElement("li", { class: "bpui-selectmenu-list-row", "data-value": d.value }, this.element.fontshadow.children[1].children[2]); temp.innerHTML = d.content; temp.onclick = () => { this.element.fontshadow.children[1].children[0].innerHTML = d.content; this.changeStyle(this.setting.shadow = d.value); }; }); } /** * 字幕位置 */ fontposition() { this.element.fontposition = API.addElement("div", {}, this.element.table); this.element.fontposition.innerHTML = \`字幕位置
        底部居中
          \`; this.position.forEach(d => { if (d.value == this.setting.position) this.element.fontposition.children[1].children[0].innerHTML = d.content; let temp = API.addElement("li", { class: "bpui-selectmenu-list-row", "data-value": d.value }, this.element.fontposition.children[1].children[2]); temp.innerHTML = d.content; temp.onclick = () => { this.element.fontposition.children[1].children[0].innerHTML = d.content; this.changePosition(this.setting.position = d.value); }; }); } /** * 字幕透明度 */ fontopacrity() { this.element.fontopacrity = API.addElement("div", {}, this.element.table); this.element.fontopacrity.innerHTML = \`
          背景不透明度
          \`; this.element.fontopacrity.children[1].value = this.setting.backgroundopacity * 100; this.element.fontopacrity.children[1].oninput = (e) => { this.changeStyle(this.setting.backgroundopacity = e.target.value / 100); }; } /** * 获取CC字幕信息 */ async getCaption(data) { try { this.subtitle = this.captions = data.data.subtitle.subtitles || []; let i = 0; // 指示字幕语言记录 this.captions.forEach((d, j) => { if (d.lan == this.subtitlePrefer) i = j; }); if (this.captions[i]) await this.setCaption(this.captions[i]); if (this.caption) { // 只在有字幕时添加面板 window.player.addEventListener('video_resize', (event) => { this.changeResize(event); }); let anchor = document.querySelector(".bilibili-player-video-btn-quality"); this.initUI(); if (!document.querySelector("#bilibili-player-subtitle-btn")) anchor.insertAdjacentElement("afterend", this.element.node); } } catch (e) { debug.error("closedCaption.js", e); } } /** * 设置CC字幕 * @param caption CC字幕对象 */ async setCaption(caption) { let data = { body: [] }; // 空字幕 if (caption && caption.subtitle_url) { this.data[caption.subtitle_url] = this.data[caption.subtitle_url] || await xhr({ url: caption.subtitle_url, responseType: "json", credentials: false }); data = this.data[caption.subtitle_url] || data; } window.player.updateSubtitle(data); // 投喂字幕数据给播放器 setTimeout(() => { if (window.player.getState() == "PLAYING") { // 刷新一次播放状态 window.player.pause(); window.player.play(); } }, 1000); if (caption && caption.subtitle_url) { this.caption = caption; // 记忆当前字幕 API.bofqiMessage(["载入字幕", this.captions[0].lan_doc]); } else API.bofqiMessage("关闭字幕"); } } API.closedCaption = new ClosedCaption(); //# sourceURL=API://@Bilibili-Old/do/closedCaption.js`; /*!***********************!*/ /**/modules["danmakuHashId.js"] = /*** ./dist/do/danmakuHashId.js ***/ `{ API.addCss(API.getModule("danmakuHashId.css")); class DanmakuHashId { static count = 0; // 正在查询弹幕数 static catch = {}; // 已查询弹幕缓存 count = 0; // 当前查询弹幕序号 hash; // 当前弹幕哈希值 mid; // 当前弹幕mid node; dm; constructor(crc) { // 设置正在查询的弹幕数量 DanmakuHashId.count = DanmakuHashId.count ? DanmakuHashId.count + 1 : 1; // 当前查询弹幕排序 this.count = DanmakuHashId.count; // 临时缓存已查询的 mid DanmakuHashId.catch = DanmakuHashId.catch || {}; this.hash = crc; this.mid = API.midcrc(this.hash); this.getInfo(); } async getInfo() { try { this.node = document.querySelector(".bilibili-player-context-menu-container.active"); if (!this.node) return setTimeout(() => { this.getInfo(); }, 100); this.node = this.node.children[0]; let j = 0; // 找到的节点序号 for (let i = this.node.children.length - 1; i >= 0; i--) { if (this.node.children[i].textContent.includes("mid")) { this.dm = this.node.children[i]; j++; if (this.count === j) break; } } if (!this.dm) return setTimeout(() => { this.getInfo(); }, 100); if (this.dm.tagName != "LI") return; DanmakuHashId.catch[this.mid] = DanmakuHashId.catch[this.mid] || API.jsonCheck(await xhr({ url: Format.objUrl("https://api.bilibili.com/x/web-interface/card", { mid: this.mid }) })); this.dm.innerHTML = '
          ' + DanmakuHashId.catch[this.mid].data.card.name + ' ' + DanmakuHashId.catch[this.mid].data.card.sex + '
          '; DanmakuHashId.count--; } catch (e) { DanmakuHashId.count--; toast.error("danmakuHashId.js", e); } } } window.danmakuHashId = (crc) => { try { const check = new DanmakuHashId(crc); return \`hash: \${check.hash} mid: \${check.mid}\`; } catch (e) { toast.error("danmakuHashId.js", e); } }; } //# sourceURL=API://@Bilibili-Old/do/danmakuHashId.js`; /*!***********************!*/ /**/modules["infoNewNumber.js"] = /*** ./dist/do/infoNewNumber.js ***/ `API.jsonphook("api.bilibili.com/x/web-interface/online", undefined, obj => { obj.data && (obj.data.region_count[165] = obj.data.region_count[202]); return obj; }, false); API.scriptBlock(["/web-feed/", "unread?"]); //# sourceURL=API://@Bilibili-Old/do/infoNewNumber.js`; /*!***********************!*/ /**/modules["localMedia.js"] = /*** ./dist/do/localMedia.js ***/ `class LocalMedia { data = { xml: [], json: [], mp4: [] }; offset = 0; // 弹幕当前偏移 keyboard = false; // 是否已绑定键盘事件 constructor(files) { this.change(files); } /** * 读取文件地址 */ change(files) { const file = files; if (file.length === 0) { return toast.warning("请选择本地视频或弹幕文件!", "视频:.mp4(且符合浏览器支持的编码)", "弹幕:.xml, .json"); } this.data = { xml: [], json: [], mp4: [] }; this.data = Array.from(file).reduce((d, i) => { /\\.xml\$/.test(i.name) && d.xml.push(i); // xml弹幕 /\\.json\$/.test(i.name) && d.json.push(i); // json弹幕 /\\.mp4\$/.test(i.name) && d.mp4.push(i); // mp4视频 return d; }, this.data); if (!this.data.xml[0] && !this.data.json[0] && !this.data.mp4[0]) { return toast.warning("未能识别到任何有效文件信息 →_→"); } this.video(); this.danmaku(); } /** * 读取文件内容 * @param file 记录本地文件信息的 file 对象 */ readFile(file) { return new Promise((resolve, reject) => { if (!file) reject(toast.error('无效文件路径!')); const reader = new FileReader(); reader.readAsText(file, 'utf-8'); reader.onload = () => { resolve(reader.result); }; reader.onerror = () => { reject(toast.error('读取文件出错,请重试!')); }; }); } /** * 载入弹幕 */ async danmaku() { if (!API.danmaku.loadLocalDm) { return toast.error("载入本地弹幕失败:本地弹幕组件丢失!"); } if (!this.data.xml[0] && !this.data.json[0]) return; this.data.xml.forEach(async (d, i) => { // 读取xml弹幕 let data = await this.readFile(d); toast("本地弹幕:" + d.name, "载入模式:" + ((i || config.concatDanmaku) ? "与当前弹幕合并" : "替换当前弹幕")); API.danmaku.loadLocalDm(data, Boolean(i) || config.concatDanmaku); }); this.data.json.forEach(async (d, i) => { // 读取json弹幕 let data = JSON.parse(await this.readFile(d)) || []; toast("本地弹幕:" + d.name, "载入模式:" + ((this.data.xml[0] || i || config.concatDanmaku) ? "与当前弹幕合并" : "替换当前弹幕")); window.player?.setDanmaku(data, this.data.xml[0] || Boolean(i) || config.concatDanmaku); }); API.bofqiMessage(); this.offset = 0; // 记录或重置弹幕偏移时间 if (!window.player?.offsetDanmaku) return toast.error("绑定键盘事件失败:弹幕偏移组件丢失!"); else { toast("已绑定键盘事件", "可以通过键盘 , 和 . 两个键(即上标为 < 和 > 的两个键)提前或延后弹幕偏移,频度1秒/次"); if (!this.keyboard) { this.keyboard = true; document.addEventListener("keydown", (ev) => { switch (ev.key) { case ",": window.player.offsetDanmaku(-1); this.offset--; API.bofqiMessage(["弹幕偏移:", \`\${this.offset} 秒\`]); break; case ".": window.player.offsetDanmaku(1); this.offset++; API.bofqiMessage(["弹幕偏移:", \`\${this.offset} 秒\`]); break; default: break; } }); } } } /** * 载入视频 */ video() { if (this.data.mp4[0]) { toast.warning("载入本地视频中...", "请无视控制台大量报错!"); let video = document.querySelector("#bilibiliPlayer > div.bilibili-player-area.video-state-pause > div.bilibili-player-video-wrap > div.bilibili-player-video > video"); video.src = URL.createObjectURL(this.data.mp4[0]); toast.success("本地视频:" + this.data.mp4[0].name); document.querySelector(".bilibili-player-video-time-total").textContent = this.time(video.duration); // 修复总时长 } } /** * 格式化时间轴 * @param time 时间/秒 * @returns mm:ss */ time(time) { time = Number(time) || 0; let s = time % 60; let m = (time - s) / 60; s = (Array(2).join('0') + s).slice(-2); m = m < 10 ? (Array(2).join('0') + m).slice(-2) : m; return \`\${m}:\${s}\`; } } API.localMedia = LocalMedia; //# sourceURL=API://@Bilibili-Old/do/localMedia.js`; /*!***********************!*/ /**/modules["logReport.js"] = /*** ./dist/do/logReport.js ***/ `{ Object.defineProperty(window, "reportObserver", { get: () => undefined, set: v => true }); Object.defineProperty(window, "reportMsgObj", { get: () => undefined, set: v => true }); API.xhrhookasync("data.bilibili.com", undefined, undefined, false); API.xhrhookasync("data.bilivideo.com", undefined, undefined, false); API.scriptBlock("log-reporter.js"); } //# sourceURL=API://@Bilibili-Old/do/logReport.js`; /*!***********************!*/ /**/modules["manage.js"] = /*** ./dist/do/manage.js ***/ `{ class Config { box; constructor() { this.box = API.element.popupbox({ maxWidth: "360px", maxHeight: "300px" }); API.addElement("div", { style: 'text-align: center;font-size: 16px;font-weight: bold;margin-bottom: 10px;' }, this.box, \`设置数据\`); API.addElement("div", { style: 'margin-bottom: 10px;' }, this.box, \`
          设置数据包含您个人对于设置的自定义调整,不包括内置的模块、安装的第三方模块以及各种功能缓存的数据。您可以选择恢复默认数据、导出为本地文件或者从本地文件中恢复。
          \`); this.box.appendChild(API.element.hr()); const body = API.addElement("div", { style: "display: flex;align-items: center;justify-content: space-around;" }, this.box); body.appendChild(API.element.button(() => { this.restore(); }, "默认", 0)); body.appendChild(API.element.button(() => { this.output(); }, "导出", 0)); body.appendChild(API.element.file((v) => { this.input(v); }, false, "导入", [".json"])); } restore() { GM.deleteValue("config"); toast.warning("已恢复默认数据,请及时刷新页面避免数据紊乱!"); API.alertMessage(\`已恢复默认数据,请及时刷新页面避免数据紊乱!\`, "恢复默认设置").then(d => { d && location.reload(); }); } output() { API.saveAs(JSON.stringify(GM.getValue("config"), undefined, "\\t"), \`config \${Format.timeFormat(undefined, true)}.json\`, "application/json"); } input(v) { v && v[0] && API.readAs(v[0]).then(d => { const data = JSON.parse(d); GM.setValue("config", data); toast.success("已导入本地设置数据,请刷新页面生效!"); }); } } new Config(); } //# sourceURL=API://@Bilibili-Old/do/manage.js`; /*!***********************!*/ /**/modules["parameterTrim.js"] = /*** ./dist/do/parameterTrim.js ***/ `class ParameterTrim { /** * 过滤参数 * */ param = [ "spm_id_from", "from_source", "msource", "bsource", "seid", "source", "session_id", "visit_id", "sourceFrom", "from_spmid", "share_source", "share_medium", "share_plat", "share_session_id", "share_tag", "unique_k" ]; /** * 地址变动参考 */ url = []; /** * 地址栏 */ location() { this.url[1] = location.href; // 暂存URL,以便比较URL变化 if (this.url[0] != this.url[1]) { let href = this.triming(location.href); // 处理链接 window.history.replaceState(window.history.state, "", href); // 推送到地址栏 this.url[0] = location.href; // 刷新暂存 } } /** * 处理a标签 * @param list a标签集 */ anchor(list) { list.forEach((d) => { if (!d.href) return; d.href.includes("bilibili.tv") && (d.href = d.href.replace("bilibili.tv", "bilibili.com")); d.href.includes("www.bilibili.com/tag") && (d.href = d.href.replace("tag", "topic")); d.href.includes("account.bilibili.com/login?act=exit") && (d.href = "javascript:void(0);", d.onclick = () => API.loginExit()); d.href = this.triming(d.href); }); } /** * 处理引导 * @param url 源URL * @returns URL */ triming(url) { const obj = Format.urlObj(url); obj.bvid && (obj.aid = API.abv(obj.bvid), obj.bvid = undefined); obj.aid && !Number(obj.aid) && (obj.aid = API.abv(obj.aid)); obj.from == "search" && (obj.from = undefined); this.param.forEach(d => obj[d] = undefined); return Format.objUrl(url, obj).replace(/[bB][vV]1[fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF]{9}/g, s => "av" + API.abv(s)); } click(e) { var f = e.target; for (; f && "A" !== f.tagName;) { f = f.parentNode; } if ("A" !== (null == f ? void 0 : f.tagName)) { return; } f.href && (f.href = this.triming(f.href)); } } { const parameterTrim = new ParameterTrim(); parameterTrim.location(); // 清理网址 API.switchVideo(() => { parameterTrim.location(); }); API.observerAddedNodes(async (node) => { node.querySelectorAll && parameterTrim.anchor(node.querySelectorAll("a")); node.tagName == "A" && parameterTrim.anchor([node]); }); window.addEventListener("click", e => parameterTrim.click(e), !1); } //# sourceURL=API://@Bilibili-Old/do/parameterTrim.js`; /*!***********************!*/ /**/modules["player-v2.js"] = /*** ./dist/do/player-v2.js ***/ `API.switchVideo(() => { let ready = false; // 载入时机标记 config.carousel ? API.xhrhookasync("api.bilibili.com/x/player/carousel.so", () => ready = true, async () => { let str = \`客户端下载bug反馈传送门'\`; try { const result = await xhr.get("//api.bilibili.com/pgc/operation/api/slideshow?position_id=531", { responseType: "json" }); str = result.result.reduce((s, d, i) => { s += \`\${d.title}]]>\`; return s; }, "") + ""; } catch (e) { debug.error("获取番剧推荐出错!", e); } const dom = new DOMParser().parseFromString(str, "text/xml"); return { response: dom, responseXML: dom }; }, false) : API.xhrhook("api.bilibili.com/x/player/carousel.so", () => ready = true); xhr({ url: Format.objUrl("https://api.bilibili.com/x/player/v2", { cid: API.cid, aid: API.aid }), responseType: "json", credentials: true }).catch((e) => { debug.error("autoFix.js", e); return xhr({ url: Format.objUrl("https://api.bilibili.com/x/v2/dm/view", { oid: API.cid, aid: API.aid, type: 1 }), responseType: "json", credentials: true }); }).then((data) => { API.runWhile(() => ready, () => { // CC字幕 data?.data?.subtitle?.subtitles && API.closedCaption.getCaption(data); // 分段进度条 config.segProgress && data?.data?.view_points[1] && new API.segProgress(data); }); }); }); //# sourceURL=API://@Bilibili-Old/do/player-v2.js`; /*!***********************!*/ /**/modules["playinfo.js"] = /*** ./dist/do/playinfo.js ***/ `API.xhrhook("/playurl?", args => { const obj = Format.urlObj(args[1]); obj.avid && Number(obj.bvid) && (API.aid = obj.avid); obj.bvid && !API.aid && (API.aid = API.abv(obj.bvid)); obj.cid && Number(obj.cid) && (API.cid = obj.cid); args[1].includes("84956560bc028eb7") && (args[1] = API.urlsign(args[1], {}, 8)); // 修复失效的appid args[1].includes("pgc") && (API.pgc = true); // ogv视频 }, async (obj) => { try { API.__playinfo__ = obj.responseType === "json" ? obj.response : API.jsonCheck(obj.response); } catch (e) { } }, false); //# sourceURL=API://@Bilibili-Old/do/playinfo.js`; /*!***********************!*/ /**/modules["protoDm.js"] = /*** ./dist/do/protoDm.js ***/ `{ API.importModule("worker.js"); API.importModule("webSocket.js"); const id = API.xhrhookasync("history?type=", (args) => { const param = Format.urlObj(args[1]); if (!window.player?.setDanmaku) { API.removeXhrhook(id); toast.warning("内部组件丢失!"); return false; } else if (!param.date) return false; xhr({ url: \`https://api.bilibili.com/x/v2/dm/web/history/seg.so?type=1&oid=\${API.cid}&date=\${param.date}\`, responseType: "arraybuffer", credentials: true }).then((seg) => { let dm = API.danmaku.danmakuFormat(API.danmaku.segDmDecode(seg)); window.player?.setDanmaku(dm); API.danmaku.danmaku = dm; }).catch((e) => { toast.error("载入历史弹幕失败", "请尝试刷新页面"); toast.error(e); }); return true; }, undefined, false); } //# sourceURL=API://@Bilibili-Old/do/protoDm.js`; /*!***********************!*/ /**/modules["replyList.js"] = /*** ./dist/do/replyList.js ***/ `{ let tag = true, timer; const script = config.oldReplySort ? "comment.min.js" : "comment.js"; config.trusteeship && API.scriptIntercept("comment.min.js", undefined, url => { setTimeout(() => { API.addElement("link", { rel: "stylesheet", href: "//static.hdslb.com/phoenix/dist/css/comment.min.css" }, document.head); }); const text = GM.getResourceText(script); if (!text) setTimeout(() => { toast.error("comment.js 资源加载失败!您可以在设置中临时关闭“托管原生脚本”。"); API.displaySetting("trusteeship"); }); return text; }); API.jsonphook("api.bilibili.com/x/v2/reply", url => { tag && (tag = false, API.addCss(API.getCss("comment.css")), config.oldReplySort && API.addCss(API.getCss("oldReplySort.css"))); url += "&mobi_app=android"; return url; }, undefined, false); config.commentLinkDetail && API.observerAddedNodes((node) => { if (/l_id/.test(node.id) || /reply-wrap/.test(node.className)) { clearTimeout(timer); timer = setTimeout(() => { timer = undefined; document.querySelectorAll(".comment-jump-url").forEach((d, i, e) => { if (d.href && !d.href.includes(d.text)) { const arr = d.href.split("/"); let text = arr[arr.length - 1] || arr[arr.length - 2]; text.toLowerCase().startsWith("bv") && (text = API.abv(text)); e[i].title = d.text; e[i].text = text; } }); }, 100); } }); } //# sourceURL=API://@Bilibili-Old/do/replyList.js`; /*!***********************!*/ /**/modules["section.js"] = /*** ./dist/do/section.js ***/ `API.runWhile(() => document.querySelector("#internationalHeader"), () => { if (API.path.name) return; API.addCss(".nav-item.live {width: auto;}"); document.querySelector("#internationalHeader").setAttribute("style", "visibility:hidden;"); (!window.\$?.ajax) && API.addElement("script", { type: "text/javascript", src: "//static.hdslb.com/js/jquery.min.js" }, undefined, undefined, true); ((document.querySelector(".mini-type") && !location.href.includes("blackboard/topic_list") && !location.href.includes("blackboard/x/act_list")) || /festival/.test(location.href)) ? API.addElement("div", { class: "z-top-container" }, undefined, undefined, true) : API.addElement("div", { class: "z-top-container has-menu" }, undefined, undefined, true); API.addElement("script", { type: "text/javascript", src: "//s1.hdslb.com/bfs/seed/jinkela/header/header.js" }); }); API.runWhile(() => document.querySelector(".international-footer"), () => { if (API.path.name) return; document.querySelector(".international-footer").remove(); (!window.\$?.ajax) && API.addElement("script", { type: "text/javascript", src: "//static.hdslb.com/js/jquery.min.js" }, undefined, undefined, true); API.addElement("div", { class: "footer bili-footer report-wrap-module", id: "home_footer" }); API.addElement("script", { type: "text/javascript", src: "//static.hdslb.com/common/js/footer.js" }); }); API.runWhile(() => document.querySelector("#bili-header-m"), () => { document.querySelector("#internationalHeader")?.remove(); API.addCss(API.getModule("avatarAnimation.css")); }); //# sourceURL=API://@Bilibili-Old/do/section.js`; /*!***********************!*/ /**/modules["segProgress.js"] = /*** ./dist/do/segProgress.js ***/ `class SegProgress { static cssInited = false; constructor(resp) { if (!resp.data.view_points || resp.data.view_points.length == 0) return; this.init(resp.data.view_points); } async init(view_points) { if (!SegProgress.cssInited) { SegProgress.cssInited = true; API.addCss(\` .bilibili-progress-segmentation-logo{display:inline-block;position:absolute;top:-12px;height:30px;width:1px; transition: opacity .1s} .bilibili-progress-segmentation-logo>img{position: absolute;top:-14px;transform:translate(-50%,-50%) scale(0.7);left:50%;transition:top 0.1s} .bilibili-progress-segmentation-logo>svg{position: absolute;top: -19px;width: 32px;height: 36px;transform: translate(-50%, -50%)} .bilibili-player.mode-widescreen .bilibili-progress-segmentation-logo>img, .bilibili-player.mode-webfullscreen .bilibili-progress-segmentation-logo>img, .bilibili-player.mode-fullscreen .bilibili-progress-segmentation-logo>img{top:-18px;left:50%;transform:translate(-50%,-50%) scale(1)} .bilibili-progress-segmentation{height:29px;position:absolute;top:-12px} .bilibili-progress-segmentation:hover > div > div{border-color:#fb7299;border-style:solid;border-width:0 2px;width:100%;height:3px;top:6px;left:-2px;position:relative;background:#fb7299} .bilibili-progress-segmentation > div{box-sizing:border-box;border-style:solid;border-color:#fb7299;border-left-width:2px;position:absolute;width:100%;height:6px;top:12px} .bilibili-progress-detail-chapter{top:-96px;position:absolute;width:100%;font-size:17px;font-weight:bold;color:#fff;text-shadow:0 0 5px #000} .bilibili-progress-segmentation:last-child > div{border-right-width:2px} .bilibili-player-filter-chapter:hover{color:#00a1d6} .bilibili-player-chapterList{position:relative;height:100%;width:100%;overflow:auto} .bilibili-player-chapterList::-webkit-scrollbar{width:6px} .bilibili-player-chapterList::-webkit-scrollbar-track{border-radius:4px;background-color:#fff} .bilibili-player-chapterList::-webkit-scrollbar-thumb{border-radius:4px;background-color:#fff} .bilibili-player-chapterList:hover::-webkit-scrollbar-track{background-color:#edf2f9} .bilibili-player-chapterList:hover::-webkit-scrollbar-thumb{background-color:#a2a2a2} .bilibili-player-chapter-info{width:100%;height:72px;margin-top:5px;white-space:normal;font-size:14px;position:relative;cursor:pointer} .bilibili-player-chapter-info > img{position:absolute;left:15px;top:4px;border-radius:2px} .bilibili-player-chapter-info > p{padding-top:5px;margin:0 5px 5px 138px;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;height:43px} .bilibili-player-chapter-info:hover > p{color:#00a1d6} .bilibili-player-chapter-info > span{color:#99a2aa} .bilibili-player-chapter-info.active{background-color:#f3f3f3}\`); } let sliderTracker = document.querySelector(".bilibili-player-video-progress .bpui-slider-tracker"); // 播放进度区域,6px let sliderBar = document.getElementsByClassName("bilibili-player-video-progress-bar")[0]; let handleWidth = document.getElementsByClassName("bpui-slider-handle")[0].clientWidth; // 进度条圆形把手的宽度 let trackerWrp = document.getElementsByClassName("bpui-slider-tracker-wrp")[0]; // 进度条可控区域,28px let videoDuration = window.player.getDuration(); // 视频总时长 // 创建显示在视频预览缩略图上方的看点标题 let chptName = document.createElement("div"); chptName.className = "bilibili-progress-detail-chapter"; document.querySelector(".bilibili-player-video-progress-detail").appendChild(chptName); // 添加分段进度条 let type = view_points[0].type; // type = 1:赛事看点,type = 2:视频分段 let segDivs = []; // 存放所有分段Div for (let v of view_points) { let seg = document.createElement("div"); if (type == "1") { seg.className = "bilibili-progress-segmentation-logo"; let title = document.createElement("div"); // 看点标题 title.innerHTML = "-> " + v.content; title.className = "bilibili-progress-detail-chapter"; title.style.cssText = "width: auto; transform: translateX(-50%); display: none"; let img; if (v.logoUrl) { img = document.createElement("img"); // 看点图标 img.id = "segmentation-logo"; img.width = 32; img.height = 36; img.src = v.logoUrl; } else { img = document.createElementNS("http://www.w3.org/2000/svg", "svg"); img.setAttribute("viewBox", "0 -3 32 36"); img.innerHTML = \` \`; } img.addEventListener("mousemove", e => e.stopPropagation()); img.addEventListener("mouseenter", () => { title.style.display = ""; img.style.zIndex = "1000"; }); img.addEventListener("mouseleave", () => { title.style.display = "none"; img.style.zIndex = ""; }); img.addEventListener("click", () => window.player.seek(v.from)); seg.appendChild(title); seg.appendChild(img); } else if (type == "2") { seg.className = "bilibili-progress-segmentation"; let duration = view_points[view_points.length - 1].to; let ratio = videoDuration / duration / duration; seg.style.width = (v.to - v.from) * ratio * 100 + "%"; seg.style.left = v.from * ratio * 100 + "%"; seg.innerHTML = "
          "; seg.onmouseenter = () => chptName.innerHTML = v.content; } segDivs.push(seg); sliderTracker.appendChild(seg); } if (type == "1") { API.addCss(\`#app #bilibiliPlayer .bilibili-player-video-progress-detail > .bilibili-player-video-progress-detail-img {top:-120px} .bilibili-player-video-progress-detail > .bilibili-player-video-progress-detail-time {top:-48px}\`); function update() { for (let i = 0; i < segDivs.length; i++) { // 进度条上的鼠标坐标与视频时间点的互算公式,从bilibiliPlayer.js复制过来 // 使视频看点标记与点击进度条后实际跳转的时间点准确对应 segDivs[i].style.left = view_points[i].to / videoDuration * (trackerWrp.clientWidth - handleWidth) + handleWidth / 2 + "px"; } } setTimeout(() => update(), 500); // 等待进度条完全加载 chptName.style.top = "-150px"; let playerArea = document.getElementsByClassName("bilibili-player-area")[0], visibility = true; function hide() { if (!visibility) return; visibility = false; for (let i = 0; i < segDivs.length; i++) segDivs[i].style.opacity = "0"; setTimeout(() => { for (let i = 0; i < segDivs.length; i++) segDivs[i].style.visibility = "hidden"; }, 100); } playerArea.addEventListener("mouseleave", e => { hide(); }); playerArea.addEventListener("mousemove", e => { let clientRect = playerArea.getBoundingClientRect(); if (e.pageY < clientRect.top + window.scrollY + clientRect.height * 0.65) { hide(); } else { visibility = true; for (let i = 0; i < segDivs.length; i++) { segDivs[i].style.visibility = ""; segDivs[i].style.opacity = "1"; } } }); // 鼠标与看点图标的交互 trackerWrp.addEventListener("mousemove", e => { let closestPoint = 1e6; // 鼠标位置->视频时间点 let box = sliderBar.getBoundingClientRect(); let pos = (e.pageX - (box.left + window.scrollX - document.body.clientLeft) - handleWidth / 2) / (trackerWrp.clientWidth - handleWidth) * videoDuration; 0 > pos && (pos = 0); pos > videoDuration && (pos = videoDuration); let thumbnailArea = 80 / (trackerWrp.clientWidth - handleWidth) * videoDuration; let hitArea = trackerWrp.clientWidth > 400 ? thumbnailArea / 10 : thumbnailArea / 20; // 显示标题的鼠标坐标范围 for (let i = 0; i < view_points.length; i++) { segDivs[i].style.zIndex = ""; if (view_points[i].to >= pos - hitArea && view_points[i].to <= pos + hitArea && Math.abs(view_points[i].to - pos) < closestPoint) { chptName.innerHTML = view_points[i].content; closestPoint = Math.abs(view_points[i].to - pos); segDivs[i].style.zIndex = "1000"; } } if (closestPoint == 1e6) chptName.innerHTML = ""; }); window.player.addEventListener("video_player_resize", () => update()); trackerWrp.addEventListener("mouseleave", () => { for (let i = 0; i < segDivs.length; i++) { segDivs[i].className = "bilibili-progress-segmentation-logo"; } }); } // 添加“视频看点”面板 let wrapList = document.querySelector("div.bilibili-player-wraplist"); // 获取播放器右侧面板的容器div let panels = wrapList.children; let chptInfo = null; // 数组,存放每一看点的UI卡片 let chptPanel = document.createElement("div"); // “视频看点”面板 chptPanel.style.display = "none"; chptPanel.className = "bilibili-player-filter-wrap bilibili-player-chapterList"; wrapList.appendChild(chptPanel); let chptBtn = document.createElement("div"); // “视频看点”按钮 chptBtn.className = "bilibili-player-filter-btn bilibili-player-filter-chapter bpui-component bpui-button bpui-button-type-small button"; chptBtn.innerHTML = '视频看点'; document.querySelector("div.bilibili-player-filter").appendChild(chptBtn); // 用当前播放进度刷新面板 function refreshState() { if (!chptInfo) return; let progress = window.player.getCurrentTime(); for (let i = 0, v; i < view_points.length; i++) { v = view_points[i]; if (progress < v.to) { let active = document.querySelector(".bilibili-player-chapter-info.active"); active && active.classList.remove("active"); chptInfo[i].classList.add("active"); break; } } } let timeFormat = (t) => t < 10 ? "0" + t : t; chptBtn.onclick = () => { let activePanel = document.querySelector("div.bilibili-player-filter-btn.active"); if (activePanel == chptBtn) return; // 切换按钮的激活状态 activePanel.classList.remove("active"); chptBtn.classList.add("active"); for (let i = 0; i < panels.length; i++) { const element = panels[i]; if (element.style.display == "block") { element.style.display = "none"; break; } } // 创建各个看点对应的UI卡片 if (!chptInfo) { chptInfo = []; for (let i = 0, v; i < view_points.length; i++) { v = view_points[i]; let dura = v.to - v.from; let div = document.createElement("div"); div.className = "bilibili-player-chapter-info"; div.innerHTML = \`

          \${v.content}

          \${timeFormat(Math.floor(v.from / 60))}:\${timeFormat(v.from % 60)} \${dura >= 60 ? \`\${Math.floor(dura / 60)}分\` : ""}\${dura > 0 ? \`\${dura % 60}秒\` : ""}\`; div.onclick = (jumpto => () => { window.player.seek(jumpto); let active = document.querySelector(".bilibili-player-chapter-info.active"); active && active.classList.remove("active"); div.classList.add("active"); })(v.from); chptInfo[i] = div; chptPanel.appendChild(div); } } ; chptPanel.style.display = "block"; // 将当前的播放进度对应的UI卡片显示为灰色底色 refreshState(); }; window.player.addEventListener("video_media_seeked", refreshState); chptPanel.onmouseenter = refreshState; class timer { static handle; static start() { if (!timer.handle) timer.handle = setInterval(refreshState, 3000); } static stop() { if (timer.handle) { clearInterval(timer.handle); timer.handle = null; } } } window.player.addEventListener("video_media_playing", timer.start); window.player.addEventListener("video_media_pause", timer.stop); if (window.player.getState() == "PLAYING") timer.start(); } } API.segProgress = SegProgress; //# sourceURL=API://@Bilibili-Old/do/segProgress.js`; /*!***********************!*/ /**/modules["user-select.js"] = /*** ./dist/do/user-select.js ***/ `API.addCss(\`* { -webkit-user-select: text !important; -moz-user-select: text !important; -ms-user-select: text !important; user-select: text !important; }\`); [].forEach.call(['contextmenu', 'copy', 'cut', 'paste', 'mouseup', 'mousedown', 'keyup', 'keydown', 'drag', 'dragstart', 'select', 'selectstart'], function (event) { document.addEventListener(event, function (e) { e.stopPropagation(); }, true); }); //# sourceURL=API://@Bilibili-Old/do/user-select.js`; /*!***********************!*/ /**/modules["videoLimit.js"] = /*** ./dist/do/videoLimit.js ***/ `{ class HookTimeOut { hook; constructor() { this.hook = setTimeout; window.setTimeout = (...args) => { if (args[1] && args[1] == 1500 && args[0] && args[0].toString() == "function(){f.cz()}") { toast.warning("禁用播放器强制初始化!", ...args); return Number.MIN_VALUE; } return this.hook.call(window, ...args); }; } relese() { window.setTimeout = this.hook; } } API.xhrhook('season/user/status?', args => { args[1] = args[1].replace('bangumi.bilibili.com/view/web_api/season/user/status', 'api.bilibili.com/pgc/view/web/season/user/status'); }, obj => { const response = obj.responseType === "json" ? obj.response : JSON.parse(obj.response); if (response) { if (response.result.area_limit) { response.result.area_limit = 0; response.ban_area_show = 1; API.limit = true; } if (response.result.progress) response.result.watch_progress = response.result.progress; if (response.result.vip_info) response.result.vipInfo = response.result.vip_info; obj.response = obj.responseType === "json" ? response : JSON.stringify(response); obj.responseText = JSON.stringify(response); } }, false); API.xhrhookasync("/playurl?", args => { return API.limit || (API.pgc && API.__INITIAL_STATE__?.rightsInfo?.watch_platform); }, async (args, type) => { let response; let obj = Format.urlObj(args[1]); const hookTimeout = new HookTimeOut(); const accesskey = GM.getValue("access_key", "") || undefined; if (API.globalLimit) { const server = config.limitServer || "https://api.global.bilibili.com"; try { toast.info("尝试解除泰区限制... 访问代理服务器"); response = API.jsonCheck(await xhr.GM({ url: Format.objUrl(\`\${server}/intl/gateway/v2/ogv/playurl\`, { aid: obj.avid || API.aid, ep_id: obj.ep_id, download: "1" }) })); response = await new API.rebuildPlayerurl().ogvPlayurl(response); response = { "code": 0, "message": "success", "result": response }; API.__playinfo__ = response; toast.success(\`解除泰区限制!aid=\${API.aid}, cid=\${API.cid}\`); } catch (e) { toast.error("videoLimit.js", e); response = { "code": -404, "message": e, "data": null }; } } else if (API.limit) { obj.access_key = accesskey; obj.module = (API.__INITIAL_STATE__?.upInfo?.mid == 1988098633 || API.__INITIAL_STATE__?.upInfo?.mid == 2042149112) ? "movie" : "bangumi"; obj.fnval && (obj.fnval = API.fnval); try { toast.info("尝试解除区域限制... 访问代理服务器"); response = API.jsonCheck(await xhr.GM({ url: Format.objUrl("https://www.biliplus.com/BPplayurl.php", obj) })); response = await new API.rebuildPlayerurl().appPlayurl(response); response = { "code": 0, "message": "success", "result": response }; API.__playinfo__ = response; toast.success(\`解除区域限制!aid=\${API.aid}, cid=\${API.cid}\`); } catch (e) { toast.error("videoLimit.js", e); response = { "code": -404, "message": e, "data": null }; } } else if (API.pgc && API.__INITIAL_STATE__?.rightsInfo?.watch_platform) { obj.access_key = accesskey; obj.fnval = null; obj.fnver = null; obj.platform = "android_i"; try { toast.info("尝试解除APP限制... 使用移动端flv接口"); response = API.jsonCheck(await xhr.GM({ url: API.urlsign("https://api.bilibili.com/pgc/player/api/playurl", obj, 1) })); response = { "code": 0, "message": "success", "result": response }; API.__playinfo__ = response; toast.success(\`解除APP限制!aid=\${API.aid}, cid=\${API.cid}\`); } catch (e) { toast.error("videoLimit.js", e); response = { "code": -404, "message": e, "data": null }; } } hookTimeout.relese(); return type === "json" ? { response } : { response: JSON.stringify(response), responseText: JSON.stringify(response) }; }, false); } //# sourceURL=API://@Bilibili-Old/do/videoLimit.js`; /*!***********************!*/ /**/modules["aria2.js"] = /*** ./dist/download/aria2.js ***/ `class Aria2 { setting = {}; constructor() { config.useragent && (this.setting.userAgent = config.useragent); config.referer && (this.setting.referer = config.referer); config.filepath && (this.setting.directory = config.filepath); config.rpcToken && (this.setting.token = config.rpcToken); } /** * 生成aria2命令行参数并赋值到剪切板 * @param obj 下载配置数据 */ shell(obj) { return new Promise((r, j) => { let result = "aria2c"; obj = { ...this.setting, ...obj }; obj.urls.forEach(d => result += \` "\${d}"\`); obj.out && (result += \` --out="\${obj.out}"\`); obj.userAgent && (result += \` --user-agent="\${obj.userAgent}"\`); obj.referer && (result += \` --referer="\${obj.referer}"\`); obj.directory && (result += \` --dir="\${obj.directory}"\`); obj.split && (result += \` --split="\${obj.split}"\`); obj.header && Object.entries(obj.header).forEach(d => result += \` --header="\${d[0]}: \${d[1]}"\`); navigator.clipboard.writeText(result).then(r, e => j(e)); }); } /** * 以rpc方式发送aria2下载数据 * @param obj 下载配置数据 */ rpc(obj) { obj = { ...this.setting, ...obj }; const options = {}; obj.out && (options.out = obj.out); obj.userAgent && (options["user-agent"] = obj.userAgent); obj.referer && (options["referer"] = obj.referer); obj.directory && (options["dir"] = obj.directory); obj.split && (options["split"] = obj.split); obj.header && (options["header"] = obj.header); return this.postMessage("aria2.addUri", obj.id || new Date().getTime(), [obj.urls, options]); } /** * rpc发送接口 * @param method 请求类型 * @param id 请求唯一标志 * @param params 请求参数 * @returns Promise托管的请求结果 */ postMessage(method, id, params = []) { const url = \`\${config.rpcServer}:\${config.rpcPort}/jsonrpc\`; config.rpcToken && params.unshift(\`token:\${config.rpcToken}\`); return new Promise((r, j) => { xhr({ url: url, method: "POST", responseType: "json", data: JSON.stringify({ method, id, params }) }).then(d => { d.error && j(d.error); d.result && r(d.result); }).catch(e => { xhr({ url: Format.objUrl(url, { method, id, params: API.base64.encode(JSON.stringify(params)) }), method: "GET", responseType: "json" }).then(d => { d.error && j(d.error); d.result && r(d.result); }).catch(() => j(e)); }); }); } /** * 查询aria2版本,用于测试aria2 rpc链接情况 * @returns Promise托管的aria2版本信息 */ getVersion() { return this.postMessage("aria2.getVersion", new Date().getTime()); } } API.aria2 = new Aria2(); //# sourceURL=API://@Bilibili-Old/download/aria2.js`; /*!***********************!*/ /**/modules["download.js"] = /*** ./dist/download/download.js ***/ `{ class Download { /** * 下载面板 */ table; /** * 已获取类型列表 */ type = []; /** * 整理出的链接列表 */ links = []; /** * url序号对应的质量信息 */ quality = { 100029: '4K', 100028: '1080P60', 100027: '1080P+', 100026: '1080P', 100024: '720P', 100023: '480P', 100022: '360P', 30280: "320Kbps", 30260: "320Kbps", 30259: "128Kbps", 30257: "64Kbps", 30255: "AUDIO", 30250: "ATMOS", 30232: "128Kbps", 30216: "64Kbps", 30127: "8K", 30126: "Dolby", 30125: "HDR", 30121: "4K", 30120: "4K", 30116: '1080P60', 30112: '1080P+', 30106: '1080P60', 30102: '1080P+', 30080: '1080P', 30077: '1080P', 30076: '720P', 30074: '720P', 30066: '720P', 30064: '720P', 30048: "720P", 30033: '480P', 30032: '480P', 30016: '360P', 30015: '360P', 30011: '360P', 464: '预览', 336: "1080P", 320: "720P", 288: "480P", 272: "360P", 208: "1080P", 192: "720P", 160: "480P", 127: "8K", 126: "Dolby", 125: "HDR", 120: "4K", 116: "1080P60", 112: "1080P+", 80: "1080P", 74: "720P60", 64: "720P", 48: "720P", 32: "480P", 16: "360P", 15: "360P" }; /** * 视频编码信息对应的id,可能不完整 */ codec = { hev: [30127, 30126, 30125, 30121, 30106, 30102, 30077, 30066, 30033, 30011], avc: [30120, 30112, 30080, 30064, 30032, 30016], av1: [100029, 100028, 100027, 100026, 100024, 100023, 100022] }; /** * 颜色表 */ color = { "8K": "background-color: #ffe42b;background-image: linear-gradient(to right, #ffe42b, #dfb200);", "Dolby": "background-color: #ffe42b;background-image: linear-gradient(to right, #ffe42b, #dfb200);", "ATMOS": "background-color: #ffe42b;background-image: linear-gradient(to right, #ffe42b, #dfb200);", "AUDIO": "background-color: #ffe42b;background-image: linear-gradient(to right, #ffe42b, #dfb200);", "HDR": "background-color: #ffe42b;background-image: linear-gradient(to right, #ffe42b, #dfb200);", "4K": "background-color: #c0f;background-image: linear-gradient(to right, #c0f, #90f);", "1080P60": "background-color: #c0f;background-image: linear-gradient(to right, #c0f, #90f);", "1080P+": "background-color: #f00;background-image: linear-gradient(to right, #f00, #c00);", "1080P": "background-color: #f00;background-image: linear-gradient(to right, #f00, #c00);", "720P60": "background-color: #f90;background-image: linear-gradient(to right, #f90, #d70);", "720P": "background-color: #f90;background-image: linear-gradient(to right, #f90, #d70);", "480P": "background-color: #00d;background-image: linear-gradient(to right, #00d, #00a);", "360P": "background-color: #0d0;", "mp4": "background-color: #e0e;", "av1": "background-color: #feb;", "avc": "background-color: #07e;", "hev": "background-color: #7ba;", "aac": "background-color: #07e;", "flv": "background-color: #0dd;", "320Kbps": "background-color: #f00;background-image: linear-gradient(to right, #f00, #c00);", "128Kbps": "background-color: #f90;background-image: linear-gradient(to right, #f90, #d70);", "64Kbps": "background-color: #0d0;" }; constructor() { // 切P后清除下载数据并移除下载面板 API.switchVideo(() => { this.type = []; this.links = []; this.table && this.table.remove(); }); } /** * 整理playurl返回值并提取其中的媒体链接记录到links * @param playinfo ajax返回的JSON数据 */ decodePlayinfo(playinfo) { playinfo.data && this.decodePlayinfo(playinfo.data); playinfo.result && this.decodePlayinfo(playinfo.result); playinfo.durl && this.durl(playinfo.durl); playinfo.dash && this.dash(playinfo.dash); } /** * 根据url确定画质/音质信息 * 需要维护quality表 * @param url 多媒体url * @param id 媒体流id * @returns 画质/音质信息 */ getQuality(url, id) { return this.quality[this.getID(url)] || (id && this.quality[id]) || "N/A"; } /** * 从url中提取可能的id * @param url 多媒体url */ getID(url) { return Number(/[0-9]+\\.((flv)|(mp4)|(m4s))/.exec(url)[0].split(".")[0]); } /** * 整理dash部分 * @param dash dash信息 */ dash(dash) { dash.video && this.dashVideo(dash.video, dash.duration); dash.audio && this.dashAudio(dash.audio, dash.duration); dash.dolby && dash.dolby.audio && Array.isArray(dash.dolby.audio) && this.dashATMOS(dash.dolby.audio, dash.duration); } /** * 整理dash视频部分 * @param video dash视频信息 * @param duration duration信息,配合bandwidth能计算出文件大小 */ dashVideo(video, duration) { video.forEach(d => { const url = d.baseUrl || d.base_url; let type = ""; if (!url) return; if (d.codecs) { type = d.codecs.includes("avc") ? "avc" : d.codecs.includes("av01") ? "av1" : "hev"; } else { const id = this.getID(url); type = this.codec.hev.find(d => d === id) ? "hev" : "avc"; } !this.type.includes("dash") && this.type.push("dash"); this.links.push({ type: type, url: url, quality: this.getQuality(url, d.id), size: Format.sizeFormat(d.bandwidth * duration / 8), backupUrl: d.backupUrl || d.backup_url }); }); } /** * 整理dash音频部分 * @param audio dash音频信息 * @param duration duration信息,配合bandwidth能计算出文件大小 */ dashAudio(audio, duration) { audio.forEach(d => { const url = d.baseUrl || d.base_url; url && this.links.push({ type: "aac", url: url, quality: this.getQuality(url, d.id), size: Format.sizeFormat(d.bandwidth * duration / 8), backupUrl: d.backupUrl || d.backup_url }); }); } /** * 整理dash杜比全景声部分 * @param audio 杜比全景声信息 * @param duration duration信息,配合bandwidth能计算出文件大小 */ dashATMOS(audio, duration) { audio.forEach(d => { const url = d.baseUrl || d.base_url; url && this.links.push({ type: "aac", url: url, quality: this.getQuality(url, d.id), size: Format.sizeFormat(d.bandwidth * duration / 8), backupUrl: d.backupUrl || d.backup_url }); }); } /** * 整理durl部分 * @param durl durl信息 */ durl(durl) { let index = 0; // flv分段标记 durl.forEach(d => { const link = { type: "", url: d.url, quality: this.getQuality(d.url, d.id), size: Format.sizeFormat(d.size), backupUrl: d.backupUrl || d.backup_url }; switch (d.url.includes("mp4?")) { case true: link.type = "mp4"; !this.type.includes("mp4") && this.type.push("mp4"); break; case false: link.type = "flv"; index++; link.flvSplit = index; !this.type.includes("flv") && this.type.push("flv"); break; } this.links.push(link); }); } /** * 右键下载响应 */ async contentMenu() { if (API.aid && API.cid) { if (!this.links[0]) { !config.TVresource && API.__playinfo__ && this.decodePlayinfo(API.__playinfo__); const result = await Promise.all(config.downloadList.reduce((s, d) => { !this.type.includes(d) && s.push(this.getContent(d)); return s; }, [])); result.forEach(d => d && this.decodePlayinfo(d)); await this.getOther(); } const title = this.getTitle(); this.links.forEach(d => { !d.filename && (d.filename = title); }); this.showTable(); } } /** * 添加视频之外的下载数据 */ async getOther() { if (!config.ifDlDmCC) return; if (API.danmaku.danmaku) { const url = config.dlDmType == "json" ? JSON.stringify(API.danmaku.danmaku, undefined, "\\t") : API.danmaku.toXml(API.danmaku.danmaku); this.links.push({ url: url, type: "其他", quality: "弹幕", size: Format.sizeFormat(API.strSize(url)), filename: \`\${this.getTitle()}-\${API.cid}.\${config.dlDmType}\` }); } if (API.closedCaption.subtitle) { API.closedCaption.subtitle.forEach(d => { this.links.push({ url: !d.subtitle_url.includes(":") ? d.subtitle_url.replace("//", "https://") : d.subtitle_url, type: "其他", quality: d.lan_doc, size: "N/A" }); }); } const data = await API.getAidInfo(API.aid); data && data?.View?.pic && this.links.push({ url: data.View.pic, type: "其他", quality: "封面", size: "N/A", amylose: true }); } /** * 封装请求链接 * 用于过滤Promise.all请求错误 * @param d 请求类型 * @returns 请求结果 */ async getContent(d) { let result; try { switch (d) { case "dash": result = API.pgc ? await new API.url().getJson(config.TVresource ? "api.bilibili.com/pgc/player/api/playurltv" : "api.bilibili.com/pgc/player/web/playurl", { avid: API.aid, cid: API.cid, fnver: 0, fnval: API.fnval }, true) : await new API.url().getJson(config.TVresource ? "api.bilibili.com/x/tv/ugc/playurl" : "api.bilibili.com/x/player/playurl", { avid: API.aid, cid: API.cid, fnver: 0, fnval: API.fnval }, true); break; case "flv": result = API.pgc ? await new API.url().getJson(config.TVresource ? "api.bilibili.com/pgc/player/api/playurltv" : "api.bilibili.com/pgc/player/web/playurl", { avid: API.aid, cid: API.cid, qn: config.downloadQn }, true) : await new API.url().getJson(config.TVresource ? "api.bilibili.com/x/tv/ugc/playurl" : "api.bilibili.com/x/player/playurl", { avid: API.aid, cid: API.cid, qn: config.downloadQn }, true); break; case "mp4": result = API.pgc ? await new API.url().getJson("api.bilibili.com/pgc/player/api/playurlproj", { cid: API.cid }, true) : await new API.url().getJson("app.bilibili.com/v2/playurlproj", { cid: API.cid }, true); break; } } catch (e) { } return result; } /** * 呼出下载面板 */ showTable() { if (!this.links[0]) return toast.warning("未获取到任何下载数据!"); this.table && this.table.remove(); this.table = API.addElement("div"); const real = this.table.attachShadow({ mode: "closed" }); const root = API.addElement("div", { class: "table" }, real); const cells = {}; new API.clickRemove(this.table); API.addCss(API.getCss("download.css"), undefined, real); this.links.forEach(d => { const cell = cells[d.type] || API.addElement("div", { class: "cell" }, root); if (!cells[d.type]) { cells[d.type] = cell; const div = API.addElement("div", { class: "type" }, cell, d.type); this.color[d.type] && div.setAttribute("style", this.color[d.type]); } const item = API.addElement("a", { class: "item", target: "_blank" }, cell); const up = API.addElement("div", { class: "up" }, item, d.quality + (d.flvSplit ? "x" + d.flvSplit : "")); this.color[d.quality] && up.setAttribute("style", this.color[d.quality]); API.addElement("div", { class: "down" }, item, d.size); d.amylose ? item.href = d.url : (item.onclick = () => { /^https?:\\/\\/([\\w-]+\\.)+[\\w-]+(\\/[\\w-,.\\/?%&=]*)?/.test(d.url) ? this.postData(d) : API.saveAs(d.url, d.filename || \`download \${Format.timeFormat(undefined, true)}.txt\`, d.contentType || "text/plain"); }); }); } /** * 点击下载按钮回调 * @param data 被点击的下载数据 */ postData(data) { !Reflect.has(data, "_name") && (data.filename = this.setFinalName(data)); switch (config.downloadMethod) { case "ef2": API.ef2.sendLinkToIDM({ url: data.url, out: data.filename }); break; case "aria2": API.aria2.shell({ urls: [data.url], out: data.filename }) .then(() => toast.success(\`已复制aria2命令行到剪切板,在cmd等shell中使用即可下载~\`)) .catch(e => toast.error(\`复制aria2命令行失败!\`, e)); break; case "aira2 RPC": API.aria2.rpc({ urls: [data.url], out: data.filename }) .then(GID => toast.success(\`已添加下载任务到aria2 RPC主机,任务GID:\${GID}\`)) .catch(e => toast.error(\`添加下载任务到aria2 RPC主机出错!\`, e)); break; default: (config.TVresource && (data.type === "flv" || data.type === "avc" || data.type === "hev" || data.type === "av1" || data.type === "aac")) ? toast.warning("TV源视频流不支持本方式下载,请在设置中另选下载方式或关闭请求TV源!") : this.rightKey(data); } } /** * 获取当前视频标题 * @returns 标题 */ getTitle() { const title = document.title.split("_哔哩")[0]; const p = location.href.includes("p=") ? location.href.match(/p=\\d+/)[0].split("=")[1] : ""; return p ? title + p : title; } /** * 从URL中提取可能的文件名和拓展名 * @param url * @returns [文件名,拓展名] */ getUrlFileName(url) { url = url.split("?")[0]; const arr = url.split("/"); return arr[arr.length - 1].split("."); } /** * 合成最终文件名 * @param obj.url 下载url,从中提取可能的文件名,优先级最低 * @param obj.type 下载资源类型,用于决定后缀名,优先级次之 * @param obj.filename 预设定文件名,优先级最高 * @returns 文件名 */ setFinalName(obj) { let adv = ""; let arr = this.getUrlFileName(obj.url); let ars = obj.filename.split("."); switch (obj.type) { case "mp4": adv = ".mp4"; break; case "flv": adv = ".flv"; break; case "aac": adv = ".m4a"; break; case "avc": adv = ".avc.m4v"; break; case "hev": adv = ".hevc.m4v"; break; } adv = ars[1] ? \`.\${ars.pop()}\` : adv ? adv : arr[1] ? \`.\${arr.pop()}\` : ""; Reflect.set(obj, "_name", true); return (obj.filename || arr[0]) + \`\${obj.flvSplit ? "x" + obj.flvSplit : ""}.\${obj.quality}\${adv}\`; } /** * 右键下载 * @param data 下载数据 */ rightKey(data) { const root = API.element.popupbox({ width: "300px" }); API.addElement("div", { style: "text-align: center;font-weight: bold;padding-block-end: 10px;" }, root, data.filename); API.addElement("div", { style: "padding-block-end: 10px;" }, root, \`请在此处右键“另存为”以保存文件,IDM的话也可以右键“使用 IDM下载链接”。\`); API.addElement("div", { style: "font-size: 10px; padding-block-end: 10px;" }, root, '本方式下载不太稳定,不嫌麻烦的话可在设置中更换下载方式。'); } } const download = new Download(); API.download = () => download.contentMenu(); } //# sourceURL=API://@Bilibili-Old/download/download.js`; /*!***********************!*/ /**/modules["ef2.js"] = /*** ./dist/download/ef2.js ***/ `class Ef2 { setting = {}; constructor() { config.useragent && (this.setting.userAgent = config.useragent); config.referer && (this.setting.referer = config.referer); config.filepath && (this.setting.directory = config.filepath); config.IDMLater && (this.setting.sendToList = config.IDMLater); config.IDMToast && (this.setting.toastDisabled = config.IDMToast); } /** * 发送下载数据到IDM * @param data 配置IDM */ sendLinkToIDM(data) { data = { ...this.setting, ...data }; const a = document.createElement("a"); a.href = this.encode(data); a.click(); } /** * 编码ef2协议 * @param data 配置数据 * @returns ef2协议 */ encode(data) { let result = ""; Object.keys(data).forEach((d) => { switch (d) { case "cookies": result += \` -c "\${data.cookies}"\`; break; case "directory": data.directory = data.directory.replace(/\\//, "\\\\"); // 目录反斜杠可能误输入为了正斜杠 data.directory && data.directory[data.directory.length - 1] == "\\\\" && (data.directory = data.directory.substr(0, data.directory.length - 1)); // 目录最后的反斜杠可能导致引号被转义 result += \` -o "\${data.directory}"\`; break; case "out": result += \` -s "\${data.out}"\`; break; case "password": result += \` -P "\${data.password}"\`; break; case "postDate": result += \` -d "\${data.postDate}"\`; break; case "referer": result += \` -r "\${data.referer}"\`; break; case "sendToList": result += \` -q\`; break; case "toastDisabled": result += \` -f\`; break; case "url": data.url.startsWith("//") && (data.url = "https:" + data.url); // 省略协议头时默认添加http/tls头 result += \` -u "\${data.url}"\`; break; case "userAgent": result += \` -a "\${data.userAgent}"\`; break; case "userName": result += \` -U "\${data.userName}"\`; break; } }); result && result.startsWith(" ") && (result = result.substr(1, result.length)); return "ef2://" + API.base64.encode(result); } /** * 解码ef2链接为 * @param ef2ptl * @returns ef2配置信息 */ decode(ef2ptl) { ef2ptl = ef2ptl.replace("ef2://", ""); ef2ptl = API.base64.decode(ef2ptl) + " "; const key = ef2ptl.match(/-\\w /g); const value = ef2ptl.split(/-\\w /); value.shift(); return Array.from(key).reduce((s, d, i) => { value[i] && value[i].endsWith(" ") && (value[i] = value[i].substr(0, value[i].length - 1)); value[i] && value[i].endsWith("\\"") && (value[i] = value[i].substr(1, value[i].length - 2)); switch (d) { case "-c ": s.cookies = value[i]; break; case "-o ": s.directory = value[i]; break; case "-s ": s.out = value[i]; break; case "-P ": s.password = value[i]; break; case "-d ": s.postDate = value[i]; break; case "-r ": s.referer = value[i]; break; case "-q ": s.sendToList = true; break; case "-f ": s.toastDisabled = true; break; case "-u ": s.url = value[i]; break; case "-a ": s.userAgent = value[i]; break; case "-U ": s.userName = value[i]; break; } return s; }, {}); } } API.ef2 = new Ef2(); //# sourceURL=API://@Bilibili-Old/download/ef2.js`; /*!***********************!*/ /**/modules["rightKey.js"] = /*** ./dist/download/rightKey.js ***/ `API.switchVideo(() => { try { const li = document.createElement("li"); li.innerHTML = '下载视频'; li.setAttribute("class", "context-line context-menu-function bili-old-download"); li.onmouseover = () => li.setAttribute("class", "context-line context-menu-function bili-old-download hover"); li.onmouseout = () => li.setAttribute("class", "context-line context-menu-function bili-old-download"); li.onclick = () => API.download(); let flag = 0; document.querySelector("#bilibiliPlayer")?.addEventListener("DOMNodeInserted", e => { if (!flag && e.target.className && /context-line context-menu-function/.test(e.target.className)) { const node = document.querySelector(".bilibili-player-context-menu-container.black"); node && (flag = setTimeout(() => { if (node.querySelector(".context-menu-danmaku")) return; if (node.querySelector("#BOLD-dl-content")) return; if (node.contains(li)) return; node.firstChild.appendChild(li); }, 100)); } }); document.querySelector("#bilibiliPlayer")?.addEventListener("DOMNodeRemoved", e => { if (flag && e.target.className && /context-line context-menu-function/.test(e.target.className)) { flag = 0; try { li.remove(); } catch { } ; } }); } catch (e) { toast.error("dlContentMenu.js", e); } }); //# sourceURL=API://@Bilibili-Old/download/rightKey.js`; /*!***********************!*/ /**/modules["Node.js"] = /*** ./dist/hook/Node.js ***/ `{ class NodeHook { static appendChild = Node.prototype.appendChild; static insertBefore = Node.prototype.insertBefore; static jsonp = []; constructor() { this.appendChild(); this.insertBefore(); } jsonphook(url, redirect, modifyResponse, once = true) { let id; const one = Array.isArray(url) ? url : [url]; const two = function () { once && id && delete NodeHook.jsonp[id - 1]; if (redirect) try { this.src = redirect(this.src) || this.src; } catch (e) { debug.error("redirect of jsonphook", one, e); } if (modifyResponse) { const obj = Format.urlObj(this.src); const callback = obj.callback; const call = window[callback]; if (call) { window[callback] = function (v) { try { v = modifyResponse(v) || v; } catch (e) { debug.error("modifyResponse of jsonphook", one, e); } return call(v); }; } } }; return id = NodeHook.jsonp.push([one, two]); } jsonphookasync(url, condition, modifyResponse, once = true) { let id; const one = Array.isArray(url) ? url : [url]; const two = function () { try { once && id && delete NodeHook.jsonp[id - 1]; if (!condition || condition(this.src)) { const obj = Format.urlObj(this.src); const callback = obj.callback; const call = window[callback]; if (call) { modifyResponse && modifyResponse(this.src).then(d => { window[callback](d); this.dispatchEvent(new ProgressEvent("load")); }).catch(e => { this.dispatchEvent(new ProgressEvent("error")); debug.error("modifyResponse of xhrhookasync", one, e); }); } this.removeAttribute("src"); } } catch (e) { debug.error("jsonphook", one, e); } }; return id = NodeHook.jsonp.push([one, two]); } scriptBlock(url) { const one = Array.isArray(url) ? url : [url]; const two = function () { try { this.removeAttribute("src"); setTimeout(() => this.dispatchEvent(new ProgressEvent("load")), 100); } catch (e) { debug.error("脚本拦截失败!", one, e); } }; NodeHook.jsonp.push([one, two]); } scriptIntercept(url, redirect, text) { const one = Array.isArray(url) ? url : [url]; const two = function () { try { if (text) { this.text = text(this.src); this.removeAttribute("src"); setTimeout(() => { this.dispatchEvent(new ProgressEvent("load")); this?.remove(); }, 100); } else if (redirect) { this.src = redirect(this.src); } } catch (e) { debug.error("scriptIntercept", one, e); } }; return NodeHook.jsonp.push([one, two]); } removeJsonphook(id) { id >= 0 && delete NodeHook.jsonp[id - 1]; } appendChild() { Node.prototype.appendChild = function (newChild) { newChild.nodeName == 'SCRIPT' && newChild.src && (NodeHook.jsonp.forEach(d => { d[0].every(d => newChild.src.includes(d)) && d[1].call(newChild); })); return NodeHook.appendChild.call(this, newChild); }; } insertBefore() { Node.prototype.insertBefore = function (newChild, refChild) { newChild.nodeName == 'SCRIPT' && newChild.src && (NodeHook.jsonp.forEach(d => { d[0].every(d => newChild.src.includes(d)) && d[1].call(newChild); })); return NodeHook.insertBefore.call(this, newChild, refChild); }; } } const nodehook = new NodeHook(); API.jsonphook = (url, redirect, modifyResponse, once) => nodehook.jsonphook(url, redirect, modifyResponse, once); API.jsonphookasync = (url, condition, modifyResponse, once) => nodehook.jsonphookasync(url, condition, modifyResponse, once); API.scriptBlock = (url) => nodehook.scriptBlock(url); API.scriptIntercept = (url, redirect, text) => nodehook.scriptIntercept(url, redirect, text); API.removeJsonphook = (id) => nodehook.removeJsonphook(id); } //# sourceURL=API://@Bilibili-Old/hook/Node.js`; /*!***********************!*/ /**/modules["open.js"] = /*** ./dist/hook/open.js ***/ `{ const rules = []; const open = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function (...rest) { const args = [...rest]; args[1] && rules.forEach(d => { d && d[0].every(d => args[1].includes(d)) && d[1].call(this, args); }); return open.call(this, ...args); }; function xhrhook(url, modifyOpen, modifyResponse, once = true) { let id; const one = Array.isArray(url) ? url : [url]; const two = function (args) { once && id && delete rules[id - 1]; if (modifyOpen) try { modifyOpen(args); } catch (e) { debug.error("modifyOpen of xhrhook", one, e); } if (modifyResponse) try { this.addEventListener("readystatechange", () => { try { if (this.readyState === 4) { const response = { response: this.response, responseType: this.responseType }; (this.responseType === "" || this.responseType === "text") && (response.responseText = this.responseText); (this.responseType === "" || this.responseType === "document") && (response.responseXML = this.responseXML); modifyResponse(response); Object.defineProperty(this, "response", { configurable: true, value: response.response }); response.responseText && Object.defineProperty(this, "responseText", { configurable: true, value: response.responseText }); response.responseXML && Object.defineProperty(this, "responseXML", { configurable: true, value: response.responseXML }); } } catch (e) { debug.error("modifyResponse of xhrhook", one, e); } }); } catch (e) { debug.error("modifyResponse of xhrhook", one, e); } }; return id = rules.push([one, two]); } function xhrhookasync(url, condition, modifyResponse, once = true) { let id, temp; const one = Array.isArray(url) ? url : [url]; const two = function (args) { try { if (!condition || condition(args)) { temp = id && rules[id - 1]; // 临时移除同条件URL的hook,避免代理中使用了同url造成死循环 delete rules[id - 1]; this.send = () => true; // 禁用XMLHttpRequest.send (!args[2] || args[2] === true) && (this.timeout = 0); // 禁用超时 const et = setInterval(() => { this.dispatchEvent(new ProgressEvent("progress")); }, 50); Object.defineProperty(this, "status", { configurable: true, value: 200 }); Object.defineProperty(this, "readyState", { configurable: true, value: 2 }); this.dispatchEvent(new ProgressEvent("readystatechange")); modifyResponse && modifyResponse(args, this.responseType).then(d => { clearInterval(et); if (d) { Object.defineProperty(this, "response", { configurable: true, value: d.response }); d.responseType && Object.defineProperty(this, "responseType", { configurable: true, value: d.responseType }); d.responseText && Object.defineProperty(this, "responseText", { configurable: true, value: d.responseText }); d.responseXML && Object.defineProperty(this, "responseXML", { configurable: true, value: d.responseXML }); !this.responseURL && Object.defineProperty(this, "responseURL", { configurable: true, value: args[1] }); Object.defineProperty(this, "readyState", { configurable: true, value: 4 }); this.dispatchEvent(new ProgressEvent("readystatechange")); this.dispatchEvent(new ProgressEvent("load")); this.dispatchEvent(new ProgressEvent("loadend")); } }).catch(e => { this.dispatchEvent(new ProgressEvent("error")); debug.error("modifyResponse of xhrhookasync", one, e); }).finally(() => { clearInterval(et); !once && (id = rules.push(temp)); // 恢复多次监听 }); clearInterval(et); } } catch (e) { debug.error("condition of xhrhook", one, e); } }; return id = rules.push([one, two]); } API.xhrhook = (url, modifyOpen, modifyResponse, once) => xhrhook(url, modifyOpen, modifyResponse, once); API.xhrhookasync = (url, condition, modifyResponse, once) => xhrhookasync(url, condition, modifyResponse, once); API.removeXhrhook = (id) => id >= 0 && delete rules[id - 1]; } //# sourceURL=API://@Bilibili-Old/hook/open.js`; /*!***********************!*/ /**/modules["webSocket.js"] = /*** ./dist/hook/webSocket.js ***/ `{ let decoder = new TextDecoder(); let encoder = new TextEncoder(); let liveChatOld; // 对旧播放器建立的ws对象的引用 let liveChat; // 为了获取ws对象的引用,hook WebSocket.send let wsHookRunOnce = true; const wssend = WebSocket.prototype.send; WebSocket.prototype.send = function (...arg) { if (wsHookRunOnce && this.url == 'wss://broadcast.chat.bilibili.com:4095/sub') { liveChatOld = this; // 切p和掉线之后需要重新启动hook,获得新的引用 let onclose = liveChatOld.onclose; liveChatOld.onclose = function () { wsHookRunOnce = true; clearTimeout(liveChat.heatTimer); liveChat.close(); onclose.call(this); }; // 从bilibiliPlayer.js > b.prototype.xx复制过来 // 编码一个数据包 // body[Object] : 要发送的信息 // option[Number] : 数据包对应的行为 // =5 一条弹幕数据 // =7 首个数据包,建立与服务器的连接 // return[Buffer] : 包装好的数据 liveChatOld.convertToArrayBuffer = function (body, option) { let header = [{ "name": "Header Length", "key": "headerLen", "qg": 2, "offset": 4, "value": 16 }, { "name": "Protocol Version", "key": "ver", "qg": 2, "offset": 6, "value": 1 }, { "name": "Operation", "key": "op", "qg": 4, "offset": 8, "value": option }, { "name": "Sequence Id", "key": "seq", "qg": 4, "offset": 12, "value": 1 }]; let headerBuf = new ArrayBuffer(16); let viewer = new DataView(headerBuf, 0); let bodyBuf = encoder.encode(JSON.stringify(body)); viewer.setInt32(0, 16 + bodyBuf.byteLength); header.forEach(function (b) { 4 === b.qg ? viewer.setInt32(b.offset, b.value) : 2 === b.qg && viewer.setInt16(b.offset, b.value); }); return mergeArrayBuffer(headerBuf, bodyBuf); }; wsHookRunOnce = false; initLiveChat(); } wssend.call(this, ...arg); }; // 原函数位于bilibiliPlayer.js > c.a.eK 和 jsc-player > Dl.mergeArrayBuffer // 连接两个buffer function mergeArrayBuffer(headerBuf, bodyBuf) { headerBuf = new Uint8Array(headerBuf); bodyBuf = new Uint8Array(bodyBuf); var d = new Uint8Array(headerBuf.byteLength + bodyBuf.byteLength); d.set(headerBuf, 0); d.set(bodyBuf, headerBuf.byteLength); return d.buffer; } function initLiveChat() { // 数据包对应的Operation常量表 let Pl = { "WS_OP_HEARTBEAT": 2, "WS_OP_HEARTBEAT_REPLY": 3, "WS_OP_DATA": 1000, "WS_OP_BATCH_DATA": 9, "WS_OP_DISCONNECT_REPLY": 6, "WS_OP_USER_AUTHENTICATION": 7, "WS_OP_CONNECT_SUCCESS": 8, "WS_OP_CHANGEROOM": 12, "WS_OP_CHANGEROOM_REPLY": 13, "WS_OP_REGISTER": 14, "WS_OP_REGISTER_REPLY": 15, "WS_OP_UNREGISTER": 16, "WS_OP_UNREGISTER_REPLY": 17, "WS_OP_OGVCMD_REPLY": 1015, "WS_PACKAGE_HEADER_TOTAL_LENGTH": 18, "WS_PACKAGE_OFFSET": 0, "WS_HEADER_OFFSET": 4, "WS_VERSION_OFFSET": 6, "WS_OPERATION_OFFSET": 8, "WS_SEQUENCE_OFFSET": 12, "WS_COMPRESS_OFFSET": 16, "WS_CONTENTTYPE_OFFSET": 17, "WS_BODY_PROTOCOL_VERSION": 1, "WS_HEADER_DEFAULT_VERSION": 1, "WS_HEADER_DEFAULT_OPERATION": 1, "ws_header_default_sequence": 1, "WS_HEADER_DEFAULT_COMPRESS": 0, "WS_HEADER_DEFAULT_CONTENTTYPE": 0 }; // 请求头的参数表 let wsBinaryHeaderList = [{ "name": "Header Length", "key": "headerLen", "bytes": 2, "offset": 4, "value": 18 }, { "name": "Protocol Version", "key": "ver", "bytes": 2, "offset": 6, "value": 1 }, { "name": "Operation", "key": "op", "bytes": 4, "offset": 8, "value": 7 }, { "name": "Sequence Id", "key": "seq", "bytes": 4, "offset": 12, "value": 2 }, { "name": "Compress", "key": "compress", "bytes": 1, "offset": 16, "value": 0 }, { "name": "ContentType", "key": "contentType", "bytes": 1, "offset": 17, "value": 0 }]; liveChat = new WebSocket('wss://broadcast.chat.bilibili.com:7823/sub'); liveChat.binaryType = "arraybuffer"; liveChat.heatTimer = -1; // 每30秒一个心跳包 liveChat.heartBeat = function () { var i = this; clearTimeout(this.heatTimer); var e = this.convertToArrayBuffer({}, Pl.WS_OP_HEARTBEAT); this.send(e); this.heatTimer = window.setTimeout((function () { i.heartBeat(); }), 1e3 * 30); }; liveChat.onopen = function () { let body = { "room_id": "video://" + API.aid + "/" + API.cid, "platform": "web", "accepts": [1000, 1015] }; return this.send(this.convertToArrayBuffer(body, 7)); }; liveChat.onmessage = function (i) { try { var t = this.convertToObject(i.data); if (t) { switch (t.op) { case Pl.WS_OP_HEARTBEAT_REPLY: // 接收到心跳包后,服务器响应当前在线人数的数据 // 旧播放器连接的4095端口,虽然不再下发实时弹幕,但依然照常响应在线人数 // 所以暂时不用替换成新版 // this.onHeartBeatReply(t.body); break; case Pl.WS_OP_CONNECT_SUCCESS: this.heartBeat(); break; // 旧播放器只能处理(连接成功,心跳响应,实时弹幕)三种响应信息 // 新播放器新增的指令和功能就不管了 case Pl.WS_OP_CHANGEROOM_REPLY: //0 === Number(t.body.code) && this.options.onChangeRoomReply({ data : t && t.body }); break; case Pl.WS_OP_REGISTER_REPLY: //0 === Number(t.body.code) && this.options.onRegisterReply({ data : t && t.body }); break; case Pl.WS_OP_UNREGISTER_REPLY: //0 === Number(t.body.code) && this.options.onUnRegisterReply({ data : t && t.body }); break; case Pl.WS_OP_DATA: case Pl.WS_OP_BATCH_DATA: t.body.forEach(function (v) { liveChatOld.onmessage({ data: liveChatOld.convertToArrayBuffer({ cmd: 'DM', info: [v[0], v[1]] }, 5) }); }); break; case Pl.WS_OP_OGVCMD_REPLY: //this.onOgvCmdReply(t); break; default: //this.msgReply(t) } } } catch (i) { console.error("WebSocket Error : ", i); } return this; }; // jsc-player > i.prototype.convertToArrayBuffer,新版播放器的请求头信息更多,需要18字节 // 基本与liveChatOld.convertToArrayBuffer相同 liveChat.convertToArrayBuffer = function (body, option) { let headerBuf = new ArrayBuffer(Pl.WS_PACKAGE_HEADER_TOTAL_LENGTH); let viewer = new DataView(headerBuf, Pl.WS_PACKAGE_OFFSET); let bodyBuf = encoder.encode(JSON.stringify(body)); viewer.setInt32(Pl.WS_PACKAGE_OFFSET, Pl.WS_PACKAGE_HEADER_TOTAL_LENGTH + bodyBuf.byteLength); wsBinaryHeaderList[2].value = option; wsBinaryHeaderList.forEach((function (i) { 4 === i.bytes ? (viewer.setInt32(i.offset, i.value), "seq" === i.key && ++i.value) : 2 === i.bytes ? viewer.setInt16(i.offset, i.value) : 1 === i.bytes && viewer.setInt8(i.offset, i.value); })); return mergeArrayBuffer(headerBuf, bodyBuf); }; // jsc-player > i.prototype.convertToObject // convertToArrayBuffer对应的解码函数 liveChat.convertToObject = function (i) { var e = new DataView(i), t = {}; t.packetLen = e.getInt32(Pl.WS_PACKAGE_OFFSET); wsBinaryHeaderList.forEach((function (i) { 4 === i.bytes ? t[i.key] = e.getInt32(i.offset) : 2 === i.bytes ? t[i.key] = e.getInt16(i.offset) : 1 === i.bytes && (t[i.key] = e.getInt8(i.offset)); })); if (t.op && t.op === Pl.WS_OP_BATCH_DATA) { t.body = this.parseDanmaku(i, e, Pl.WS_PACKAGE_HEADER_TOTAL_LENGTH, t.packetLen); } else if (t.op && Pl.WS_OP_DATA === t.op) { t.body = this.parseDanmaku(i, e, Pl.WS_PACKAGE_OFFSET, t.packetLen); } else if (t.op && t.op === Pl.WS_OP_OGVCMD_REPLY) { t.body = ""; // this.parseOgvCmd(i, e, Pl.WS_PACKAGE_OFFSET, t.packetLen); } else if (t.op) { t.body = []; for (var a = Pl.WS_PACKAGE_OFFSET, r = t.packetLen, n = "", l = ""; a < i.byteLength; a += r) { r = e.getInt32(a); n = e.getInt16(a + Pl.WS_HEADER_OFFSET); try { l = JSON.parse(decoder.decode(i.slice(a + n, a + r))); t.body = l; } catch (e) { l = decoder.decode(i.slice(a + n, a + r)); console.error("decode body error:", new Uint8Array(i), t); } } } return t; }; // jsc-player > i.prototype.parseDanmaku liveChat.parseDanmaku = function (i, e, t, a) { for (var r, n = [], l = t; l < i.byteLength; l += a) { a = e.getInt32(l); r = e.getInt16(l + Pl.WS_HEADER_OFFSET); try { n.push(JSON.parse(decoder.decode(i.slice(l + r, l + a)))); } catch (e) { n.push(decoder.decode(i.slice(l + r, l + a))); console.error("decode body error:", new Uint8Array(i)); } } return n; }; } } //# sourceURL=API://@Bilibili-Old/hook/webSocket.js`; /*!***********************!*/ /**/modules["worker.js"] = /*** ./dist/hook/worker.js ***/ `{ let workerPostMsg = Worker.prototype.postMessage; let list_so; Worker.prototype.postMessage = function (aMessage, transferList) { if (aMessage.url && aMessage.url.includes("list.so")) { list_so = this; let triggerOnMsg = (danmaku, loadTime, parseTime) => list_so.onmessage({ data: { code: 0, danmakuArray: danmaku, loadTime: loadTime, parseTime: parseTime, sendTip: "", state: 0, textSide: "", total: danmaku.length.toString() } }); let loadDanmaku = (loadTime) => API.danmaku.getSegDanmaku().then((Segments) => { // 旧播放器需要得到耗时数据(网络请求,数据处理) loadTime = new Date() - loadTime; let parseTime = new Date(); let danmaku = API.danmaku.danmakuFormat(Segments); parseTime = new Date() - parseTime; triggerOnMsg(danmaku, loadTime, parseTime); API.danmaku.danmaku = danmaku; }); if (XMLHttpRequest.prototype.pakku_send === undefined) { loadDanmaku(new Date()); } else { // 让pakku.js载入弹幕 let url = "https://api.bilibili.com/x/v2/dm/web/seg.so?type=1&oid=" + API.cid + "&pid=" + API.aid + "&segment_index=1"; xhr({ url: url, responseType: "arraybuffer", credentials: true }).then((response) => { let Segments = API.danmaku.segDmDecode(response); // pakku.js处于“休眠中”时,不会修改响应数据,这时的response仅仅是第一个分段的弹幕数据 // 这种情况下需要主动去加载全部的分段(loadDanmaku) let i = 1; for (; i < Segments.length; i++) { // pakku.js处理过的弹幕,在出现时间上按升序排列,可以用这个特征加以区别是否应该载入完整的弹幕 if (Segments[i - 1].progress > Segments[i].progress) break; } if (i != Segments.length) loadDanmaku(new Date()); else { triggerOnMsg(API.danmaku.danmakuFormat(Segments), "(pakku.js)", "(pakku.js)"); } }); } } else { workerPostMsg.call(this, aMessage, transferList); } }; } //# sourceURL=API://@Bilibili-Old/hook/worker.js`; /*!***********************!*/ /**/modules["allDanmaku.js"] = /*** ./dist/include/allDanmaku.js ***/ `class AllDanmaku { pubdate; // 视频发布时间 today; // 当天 time; // 备份 arrP; // 备份 danmaku = []; arrT; // 临时变量 timeT; // 临时变量 callback; // 回调函数 constructor(callback) { this.callback = callback; toast("正在尝试获取全部弹幕请耐心等待。。。", "冷却延时请尽量调大,以免短时间内大量请求被临时封端口!"); this.pubdate = new Date(2009, 0); if (API.__INITIAL_STATE__) { if (API.__INITIAL_STATE__.videoData && API.__INITIAL_STATE__.videoData.pubdate) { this.pubdate = new Date(1E3 * API.__INITIAL_STATE__.videoData.pubdate); } else if (API.__INITIAL_STATE__.epInfo && API.__INITIAL_STATE__.epInfo.pub_real_time) { this.pubdate = new Date(API.__INITIAL_STATE__.epInfo.pub_real_time); } } else { let time = document.querySelector("div.tm-info.tminfo > time"); time && (this.pubdate = new Date(time.innerHTML)); } this.pubdate = Format.timeFormat(this.pubdate, true).split(" ")[0]; // 视频上传日期 this.today = Format.timeFormat(undefined, true).split(" ")[0]; // 当天日期 this.time = this.today; this.arrP = this.pubdate.split("-"); this.danmaku = []; this.init(); } /** * 按日期拉取弹幕 * @returns 调用月份判断 */ async init() { if (!API.uid) return toast.warning("本功能需要登录!"); if (!this.pubdate) return toast.warning("投稿日期获取失败!无法获取全部弹幕!"); try { // 获取当日日期 this.arrT = this.time.split("-"); // 如果年份小于投稿日,说明获取成功 if (this.arrT[0] < this.arrP[0]) return this.done(1); // 年份相等但月份小于投稿日说明获取成功 if (this.arrT[0] == this.arrP[0] && this.arrT[1] < this.arrP[1]) return this.done(1); // 年月都相等,但日期小于投稿日说明获取成功 if (this.arrT[0] == this.arrP[0] && this.arrT[1] == this.arrP[1] && this.arrT[2] < this.arrP[2]) return this.done(1); // 日期未早于投稿日,正常请求日期数据 toast("正在获取 " + this.time + " 日的弹幕。。。"); let danmaku = await API.danmaku.getHistoryDanmaku(this.time); API.danmaku.sortDmById(danmaku, "idStr"); danmaku.reverse(); // 取最早一条弹幕的时间 this.time = Format.timeFormat(danmaku[danmaku.length - 1].ctime * 1000, true).split(" ")[0]; this.danmaku = this.danmaku.concat(danmaku); toast("数据返回!已获取弹幕数:" + Format.unitFormat(this.danmaku.length)); this.arrT = this.time.split("-"); // 如果当天不是投稿日,转入日期检查 if (this.pubdate != this.today) return this.check(); // 否则结束弹幕获取,当前弹幕就是能获取到的全弹幕 this.done(1); } catch (e) { e = Array.isArray(e) ? e : [e]; toast.error("全弹幕装填", ...e); // 弹幕获取出错,载入已获取的弹幕 if (this.danmaku[0]) { toast.warning("弹幕获取出错!", "保留并载入已获取的弹幕"); this.done(); } else { this.callback && this.callback(); toast.error("弹幕获取出错!", "已退出!"); } } } /** * 按月份判断有弹幕时间 * @returns 调用获取日期弹幕或者循环月份判断 */ async check() { try { // 如果年份小于投稿日,说明获取成功 if (this.arrT[0] < this.arrP[0]) return this.done(1); // 年份相等但月份小于投稿日说明获取成功 if (this.arrT[0] == this.arrP[0] && this.arrT[1] < this.arrP[1]) return this.done(1); // 年月都相等,但日期小于投稿日说明获取成功 if (this.arrT[0] == this.arrP[0] && this.arrT[1] == this.arrP[1] && this.arrT[2] < this.arrP[2]) return this.done(1); // 日期未早于投稿日,正常请求月份数据 let data = await xhr({ url: Format.objUrl("https://api.bilibili.com/x/v2/dm/history/index", { type: 1, oid: API.cid, month: this.arrT.slice(0, 2).join("-") }), credentials: true }); data = API.jsonCheck(data).data; if (data && data[0]) { // 当月有弹幕,进入日期判断 for (let i = data.length - 1; i >= 0; i--) { let date = data[i].split("-"); if (date[2] < this.arrT[2]) { // 当日在已获取弹幕之前,记录并跳出循环 this.timeT = data[i]; break; } } if (this.timeT) { // 延时转入日期请求 this.time = this.timeT; this.timeT = undefined; toast(\`技能冷却中。。。请稍待 \${config.allDanmakuDelay} 秒钟\`); return setTimeout(() => this.init(), config.allDanmakuDelay * 1000); } else { // 当月有弹幕但都不在已请求日之前,月份 -1 重载 if (this.arrT[1] > 1) { this.arrT[1]--; this.arrT[1] = (Array(2).join('0') + this.arrT[1]).slice(-2); } else this.arrT = [this.arrT[0] - 1, 12, 31]; toast(\`获取前一个月数据 \${this.arrT.slice(0, 2).join("-")} 请稍待 \${config.allDanmakuDelay} 秒钟\`); return setTimeout(() => this.check(), config.allDanmakuDelay * 1000); } } else { // 当月无弹幕直接月份 -1 重载,月份等于 1 则取上年最后一天 if (this.arrT[1] > 1) { this.arrT[1]--; if (this.arrT[1] < 10) this.arrT[1] = (Array(2).join('0') + this.arrT[1]).slice(-2); } else this.arrT = [this.arrT[0] - 1, 12, 31]; toast(\`获取前一个月数据 \${this.arrT.slice(0, 2).join("-")} 请稍待 \${config.allDanmakuDelay} 秒钟\`); return setTimeout(() => this.check(), config.allDanmakuDelay * 1000); } } catch (e) { e = Array.isArray(e) ? e : [e]; toast.error("全弹幕装填", ...e); // 弹幕获取出错,载入已获取的弹幕 if (this.danmaku[0]) { toast.warning("弹幕获取出错!", "保留并载入已获取的弹幕"); this.done(); } else { this.callback && this.callback(); toast.error("弹幕获取出错!", "已退出!"); } } } /** * 载入弹幕 * @param boolean 判断获取成功还是失败,成功请传入真值。 */ async done(boolean) { try { // 历史弹幕里不包含代码弹幕必须额外处理 toast("正在获取BAS/代码弹幕专包。。。"); this.danmaku = this.danmaku.concat(await API.danmaku.getSegDanmaku(undefined, undefined, true)); toast("数据返回!正在整合。。。"); } catch (e) { } let danmaku = API.danmaku.danmakuFormat(this.danmaku, API.aid); if (boolean) toast.success("全弹幕获取成功,正在装填。。。", "总弹幕量:" + Format.unitFormat(this.danmaku.length), "同时推送至下载面板,可右键保存 π_π"); window.player?.setDanmaku(danmaku); API.danmaku.danmaku = danmaku; this.callback && this.callback(); } } API.allDanmaku = AllDanmaku; //# sourceURL=API://@Bilibili-Old/include/allDanmaku.js`; /*!***********************!*/ /**/modules["danmaku.js"] = /*** ./dist/include/danmaku.js ***/ `class Danmaku { static root; static protoSeg; static protoView; danmaku; constructor() { new Function(GM.getResourceText("protobuf.js"))(); // protobufjs引擎 Danmaku.root = window.protobuf.Root.fromJSON(API.getModule("protobuf.json")); Danmaku.protoSeg = Danmaku.root.lookupType('bilibili.DmSegMobileReply'); Danmaku.protoView = Danmaku.root.lookupType('bilibili.DmWebViewReply'); } /** * 生成xml形式的弹幕 * @param danmaku protoSeg.decode(new Uint8Array(this.response)).elems * @returns 委托对象,表示生成的xml形式的弹幕字符串 */ toXml(danmaku) { let DM = Reflect.has(danmaku[0], "idStr") ? this.danmakuFormat(danmaku) : danmaku; this.sortDmById(DM, "dmid"); let xml = DM.reduce((s, d) => { s += \`\${d.text.replace(/[<">'&]/g, (a) => { return { '<': '<', '"': '"', '>': '>', "'": ''', '&': '&' }[a]; }).replace(/(\\n|\\r\\n)/g, "/n")}\\r\\n\`; return s; }, 'chat.bilibili.com' + API.cid + '09999900e-r\\r\\n'); xml += ""; /** * remove-invalid-xml-characters.js * @link https://gist.github.com/john-doherty/b9195065884cdbfd2017a4756e6409cc * @license MIT * @see https://en.wikipedia.org/wiki/Valid_characters_in_XML */ var regex = /((?:[\\0-\\x08\\x0B\\f\\x0E-\\x1F\\uFFFD\\uFFFE\\uFFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]))/g; return xml.replace(regex, ''); } /** * 将弹幕数组按弹幕id升序排序 * @param danmaku 要排序的弹幕数组 * @param key 弹幕id的属性名,应为dmid或idStr */ sortDmById(danmaku, key) { let egx = /^\\d+\$/; for (let i = 0, d; i < danmaku.length; i++) { d = danmaku[i]; // 判断输入是否纯数字 if (!egx.test(d[key])) throw "请输入数字字符串"; // 强制转化输入为字符串 if (typeof d[key] !== "string") d[key] = String(d[key]); // 去除数字开头占位的0 d[key] = d[key].replace(/^0+/, ""); } danmaku.sort((a, b) => this.bigInt(a[key], b[key]) ? 1 : -1); } /** * 比较大小,仅用于弹幕排序 * @param num1 数字字符串 1 * @param num2 数字字符串 2 * @returns 前者大于后者返回真,否则返回假,相等也返回假 */ bigInt(num1, num2) { // 数位不同,前者大为真,否则为假 if (num1.length > num2.length) return true; else if (num1.length < num2.length) return false; else { // 数位相同,逐位比较 for (let i = 0; i < num1.length; i++) { // 任意一位前者大为真 if (num1[i] > num2[i]) return true; // 任意一位前者小为假 if (num1[i] < num2[i]) return false; // 仅当位相等时继续比较下一位 } // 包括相等情况返回假 return false; } } /** * 获取 proto 弹幕 * @param aid 弹幕所对应视频的 aid,当前视频请留空 * @param cid 弹幕所对应视频的 cid,当前视频请留空 * @param bas 是否只获取BAS/代码弹幕,默认请留空 * @returns 弹幕数组:Promise */ async getSegDanmaku(aid = API.aid, cid = API.cid, bas = false) { try { // 判断参数是否有效 aid = aid || API.aid; cid = cid || API.cid; if (!aid || !cid) throw ["弹幕参数错误!", "aid:" + aid, "cid:" + cid]; // 首先获取弹幕分片总数 let config = await xhr({ url: Format.objUrl("https://api.bilibili.com/x/v2/dm/web/view", { type: String(1), oid: String(cid), pid: String(aid) }), responseType: "arraybuffer", credentials: true }); config = Danmaku.protoView.decode(new Uint8Array(config)); // dmSge.total代表的分片总数,有时错误地为100 // 故需要按照 视频时长/分片时长(一般是360秒) 把分片总数计算出来 let pageSize = config.dmSge.pageSize ? config.dmSge.pageSize / 1000 : 360; let total = (window.player && window.player.getDuration && (window.player.getDuration() / pageSize + 1)) || config.dmSge.total; let allrequset = [], allDanmaku = []; // 其他视频的分片总数已经不能从当前window下获取 if (API.aid && (aid != API.aid)) total = config.dmSge.total; if (!bas) { // 特殊情况下只需要BAS/高级弹幕时 bas为真 for (let index = 1; index <= total; index++) { allrequset.push(xhr({ url: Format.objUrl("https://api.bilibili.com/x/v2/dm/web/seg.so", { type: String(1), oid: String(cid), pid: String(aid), segment_index: String(index) }), responseType: "arraybuffer", credentials: true })); } } // BAS弹幕 if (config.specialDms.length > 0) { for (let index = 0; index < config.specialDms.length; index++) { // 下发的是http链接,但会被chrome的安全措施拦掉,于是替换成https allrequset.push(xhr({ url: config.specialDms[index].replace("http", "https"), responseType: "arraybuffer", credentials: false })); } } // 互动弹幕 let upHighlightDm = []; // 带有蓝色“UP主”特殊标记的弹幕 if (config.commandDms.length > 0) { for (let i = 0; i < config.commandDms.length; i++) { let cdm = config.commandDms[i]; if (cdm.command == "#UP#") { cdm.styleClass = "danmaku-up-icon"; cdm.color = 16777215; cdm.pool = 0; cdm.fontsize = 25; cdm.ctime = new Date(cdm.mtime).getTime() / 1000; cdm.mode = 1; cdm.midHash = API.crc32 && API.crc32(cdm.mid); upHighlightDm.push(cdm); config.commandDms.splice(i, 1); } } if (API.loadCommandDm && API.config.commandDm) API.loadCommandDm(config.commandDms, aid, cid); } // 解码弹幕 (await Promise.all(allrequset)).forEach(d => { if (d) allDanmaku = allDanmaku.concat(Danmaku.protoSeg.decode(new Uint8Array(d)).elems); }); return allDanmaku.concat(upHighlightDm); } catch (e) { toast.error("danmaku.js", e); } } /** * 获取历史弹幕 * @param date 历史弹幕日期,yyyy-mm-dd格式:如 2009-06-24 * @param cid 弹幕所在视频的 cid,不填则取当前视频的cid * @returns 解析好的弹幕数组 */ async getHistoryDanmaku(date, cid = API.cid) { if (!date || !API.uid) return; cid = cid || API.cid; let dm = await xhr({ url: Format.objUrl("https://api.bilibili.com/x/v2/dm/web/history/seg.so", { type: String(1), oid: String(cid), date: date }), responseType: "arraybuffer", credentials: true }); return this.segDmDecode(dm); } /** * 载入本地弹幕 * @param xml 读取本地弹幕文件得到的字符串 * @param append 默认为false,即不保留已加载的弹幕。为true时,则将追加到现有弹幕上 */ loadLocalDm(xml, append) { let doc = new DOMParser().parseFromString(xml, "application/xml"); let dm = doc.querySelectorAll("d"); if (dm.length == 0) { toast.warning("从弹幕文件中没有获取到任何弹幕!"); return; } let danmaku = []; let attr, v, mode; for (let i = 0; i < dm.length; i++) { v = dm[i]; attr = v.getAttribute('p').split(","); mode = parseInt(attr[1]); danmaku[i] = { class: parseInt(attr[5]), color: parseInt(attr[3]), date: parseInt(attr[4]), dmid: attr[7], mode: mode, size: parseInt(attr[2]), stime: parseFloat(attr[0]), text: ((mode != 8 && mode != 9) ? v.textContent.replace(/(\\/n|\\\\n|\\n|\\r\\n)/g, '\\n') : v.textContent), uid: attr[6] }; } this.specialEffects(danmaku); this.sortDmById(danmaku, "dmid"); /** * bilibiliPlayer.js 21394行已经添加如下代码,用于设置弹幕池 * @param {Array} dm 弹幕数组 * @param {Boolean} append 默认为false,即不保留已加载的弹幕。为true时,则将追加到现有弹幕上 */ // setDanmaku = (dm) => {......} if (!window.player?.setDanmaku) return toast.error("刷新弹幕列表失败:播放器内部调用丢失!"); window.player?.setDanmaku(danmaku, append); } /** * 把有换行符的弹幕的zindex设为它的出现时间(progress),并且打上“字幕弹幕”标记 * @param dm 弹幕数组 */ specialEffects(dm) { let textData; for (let i = 0; i < dm.length; i++) { textData = dm[i]; if (textData.text.includes('\\n')) { textData.class = 1; textData.zIndex = textData.stime * 1000; if (!(textData.text.includes("█") || textData.text.includes("▂"))) textData.zIndex = textData.zIndex + 1; } } } segDmDecode(response) { return Danmaku.protoSeg.decode(new Uint8Array(response)).elems; } /** * 将新版弹幕数组转化为旧版弹幕数组 * @param dm 新版弹幕数组 * @param aid 视频aid,默认取当前视频aid * @returns 旧版弹幕数组 */ danmakuFormat(dm, aid) { aid = aid || API.aid; let danmaku = dm.map(function (v) { let result = { class: v.pool, color: v.color, date: v.ctime, dmid: v.idStr, mode: v.mode, size: v.fontsize, stime: v.progress / 1000, text: (v.mode != 8 && v.mode != 9) ? v.content.replace(/(\\/n|\\\\n|\\n|\\r\\n)/g, '\\n') : v.content, uid: v.midHash }; // 添加图片弹幕信息 if (v.action && v.action.startsWith("picture:")) result.picture = "//" + v.action.split(":")[1]; // 利用bilibiliPlayer.js的这行代码,可以添加指定的css类到弹幕上 // b.AH && (e.className = e.className + " " + b.AH); if (v.styleClass !== undefined) result.AH = v.styleClass; return result; }); //对av400000(2012年11月)之前视频中含有"/n"的弹幕的进行专门处理 if (aid && aid < 400000) { this.specialEffects(danmaku); } this.sortDmById(danmaku, "dmid"); return danmaku; } /** * 载入在线弹幕 * @param url 其他弹幕所在视URL */ async onlineDanmaku(url) { try { let obj = await API.urlInputCheck(url); if (obj.aid && obj.cid) { this.getSegDanmaku(obj.aid, obj.cid).then((d) => { d = this.danmakuFormat(d, obj.aid); window.player?.setDanmaku(d, config.concatDanmaku); this.danmaku = d; }); } } catch (e) { debug.error("onlineDanmaku.js", e); } } } API.danmaku = new Danmaku(); //# sourceURL=API://@Bilibili-Old/include/danmaku.js`; /*!***********************!*/ /**/modules["element.js"] = /*** ./dist/include/element.js ***/ `class ClickRemove { /** * 对一个节点添加监听,点击该节点之外的地方移除该节点 * @param ele 目标节点 */ constructor(ele) { setTimeout(() => { function remove() { ele.remove(); document.removeEventListener("click", remove); } document.addEventListener("click", remove); ele.addEventListener("click", e => e.stopPropagation()); }, 100); } } class ElementModule { /** * 弹出一个空白浮动窗口,点击该窗口外的节点该窗口会自动关闭 * 浮动窗口上的内容请通过返回的节点进行后续添加 * @param style 添加style样式,直接写进element,具有最高优先级 * @param hold 禁用自动关闭,转而提供一个关闭按钮 * @returns 浮动窗口实际可操作节点,可以往上面添加需要显示在浮动窗口上的内容 */ static popupbox(style = {}, hold) { const box = API.addElement("div", { class: "ui-popup-box" }); const real = box.attachShadow({ mode: "closed" }); const div = API.addElement("div", { class: "box" }, real); const popup = API.addElement("div", { class: "contain" }, div); API.addCss(API.getModule("ui-popup-box.css"), undefined, real); Object.keys(style).forEach(d => popup.style[d] = style[d]); hold ? this.close(div, box) : new ClickRemove(box); return popup; } /** * 添加关闭按钮 * @param ele 按钮所在节点 * @param box 点击按钮关闭的节点,不存在则取ele */ static close(ele, box) { const svg = this.svg(''); svg.setAttribute("style", "position: absolute;transform: scale(0.8);right: 10px;top: 10px;"); svg.onclick = () => box ? box.remove() : ele.remove(); ele.appendChild(svg); } /** * 封装hr标签,一条水平直线,一般用于隔断节点 * @returns 封装好的节点 */ static hr() { const hr = document.createElement("div"); const real = hr.attachShadow({ mode: "closed" }); API.addElement("div", { class: "hr" }, real); API.addCss(API.getModule("hr.css"), undefined, real); return hr; } /** * 封装svg图标标签 * @param svg svg节点字符串 * @returns 封装好的节点 */ static svg(svg) { const root = document.createElement("div"); const real = root.attachShadow({ mode: "closed" }); API.addElement("div", { class: "icon" }, real, svg); API.addCss(API.getModule("icon.css"), undefined, real); return root; } /** * 封装好的滑块快关标签 * @param callback 一个用于接收滑块开关响应的回调函数,必须,否则外部无法获取或响应开关状态 * @param value 开关初始状态,非必须,默认为false * @returns 封装好的节点 */ static switch(callback, value) { const root = document.createElement("div"); const real = root.attachShadow({ mode: "closed" }); const div = API.addElement("div", { class: "switch" }, real, \` \`); API.addCss(API.getModule("switch.css"), undefined, real); value = value ? true : false; value && (div.children[0].setAttribute("checked", "checked"), div.children[1].setAttribute("checked", "checked"), div.children[1].children[0].setAttribute("checked", "checked")); div.onclick = () => { value = !value; value ? (div.children[0].setAttribute("checked", "checked"), div.children[1].setAttribute("checked", "checked"), div.children[1].children[0].setAttribute("checked", "checked")) : (div.children[0].removeAttribute("checked"), div.children[1].removeAttribute("checked"), div.children[1].children[0].removeAttribute("checked")); callback.call(div, value); }; return root; } /** * 封装好的下拉列表标签(单选) * @param list 下拉表值组 * @param callback 一个用于接收下拉选择响应的回调函数,必须,否则外部无法获取或响应选择状态 * @param value 初始选定值 * @returns 封装好的节点 */ static select(list, callback, value) { const root = document.createElement("div"); const real = root.attachShadow({ mode: "closed" }); const div = API.addElement("div", { class: "select" }, real); const select = list.reduce((s, d) => { API.addElement("option", {}, s, d); return s; }, API.addElement("select", {}, div)); API.addCss(API.getCss("select.css"), undefined, real); select.value = value || select.options[0].text; select.onchange = () => callback.call(div, select.value); return root; } /** * 封装好的按钮标签 * @param callback 响应按钮点击的回调函数,必须,否则无法响应按钮点击事件 * @param text 按钮上的文字,默认为“确定” * @param disabled 点击按钮后的CD,单位:/s,默认为1,取0表示一直禁用 * @returns 封装好的节点 */ static button(callback, text, disabled = 1) { const root = document.createElement("div"); const real = root.attachShadow({ mode: "closed" }); const div = API.addElement("div", { class: "button" }, real, text || "确定"); API.addCss(API.getCss("button.css"), undefined, real); div.onclick = () => { div.setAttribute("disabled", "disabled"); callback.call(div); disabled && setTimeout(() => div.removeAttribute("disabled"), disabled * 1000); }; return root; } /** * 封装好的输入框,响应回车事件 * @param callback 响应输入确认的回调函数,必须,否则无法响应输入 * @param text 输入框内默认数据,非必须 * @param attribute input标签的标准属性,用于指定输入框类型等 * @param pattern 检测输入的正则表达式,将过滤非法输入并弹出toast警告 * @param button 输入框右侧带上按钮,响应按钮点击事件而非回车事件 * @param disabled 点击按钮后的CD,单位:/s,默认为1,取0表示一直禁用 * @returns 封装好的节点 */ static input(callback, text, attribute, pattern, button, disabled) { const root = document.createElement("div"); const real = root.attachShadow({ mode: "closed" }); const div = API.addElement("div", { class: "input" }, real); const input = API.addElement("input", {}, div); API.addCss(API.getCss("input.css"), undefined, real); attribute && Object.entries(attribute).forEach(d => { input.setAttribute(d[0], d[1]); }); text && (input.value = text); button ? div.appendChild(this.button(function () { if (pattern && !pattern.test(input.value)) return toast.warning(\`值 \${input.value} 不符合要求!\`, \`正则表达式:\${pattern.toString()}\`); callback.call(input, input.value); }, button, disabled)) : input.onchange = () => { if (pattern && !pattern.test(input.value)) return toast.warning(\`值 \${input.value} 不符合要求!\`, \`正则表达式:\${pattern.toString()}\`); callback.call(input, input.value); }; return root; } /** * 封装好的文件选择按钮,特化版的输入框 * @param callback 响应文件选择结果的回调函数,必须,否则无法响应文件选择 * @param multiple 是否允许多选,默认为false * @param text 选择按钮上的文字,默认为“选择” * @param accept 指定文件类型拓展名组,不指定默认取所有类型文件 * @returns 封装好的节点 */ static file(callback, multiple, text = "选择", accept) { const root = document.createElement("div"); const real = root.attachShadow({ mode: "closed" }); const input = API.addElement("input", { type: "file", style: "width: 0;position: absolute;" }, real); accept && (input.accept = accept.join(",")); multiple && (input.multiple = true); real.appendChild(this.button(() => input.click(), text, 0)); input.onchange = () => input.files && callback.call(input, input.files); return root; } /** * 封装好的复选框(多选) * @param list 复选框的值组 * @param callback 响应选择操作的回调函数,必须,否则无法响应文件选择 * @param value list中的默认选中数据组,非必须 * @returns 封装好的节点 */ static checkbox(list, callback, value = []) { const root = document.createElement("div"); const real = root.attachShadow({ mode: "closed" }); const div = API.addElement("div", { class: "box" }, real); API.addCss(API.getCss("checkbox.css"), undefined, real); const checkboxs = list.reduce((s, d) => { s.push(API.addElement("div", { class: "checkbox" }, div, \`
          \${d}
          \`)); return s; }, []); const checks = list.reduce((s, d) => { s.push(value.includes(d)); return s; }, []); checkboxs.forEach((d, i) => { checks[i] && (d.children[0].children[0].setAttribute("checked", "checked"), d.children[0].children[1].setAttribute("checked", "checked")); d.onclick = () => { checks[i] = !checks[i]; checks[i] ? (d.children[0].children[0].setAttribute("checked", "checked"), d.children[0].children[1].setAttribute("checked", "checked")) : (d.children[0].children[0].removeAttribute("checked"), d.children[0].children[1].removeAttribute("checked")); callback.call(div, checks.reduce((s, d, i) => { d && s.push(list[i]); return s; }, [])); }; }); return root; } /** * 封装好的进度条,自适应父节点width * @param detail 进度条配置,双向绑定:**修改其中的值会及时体现在该进度条上** * @returns 封装好的节点 */ static progress(detail) { let { min, max, value, color, nocolor, display } = detail; const root = document.createElement("div"); const real = root.attachShadow({ mode: "closed" }); API.addCss(API.getCss("progress.css"), undefined, real); const progress = API.addElement("div", { class: "progress" }, real); const progressContainer = API.addElement("div", { class: "progressContainer", title: "0%" }, progress); const secondaryProgress = API.addElement("div", { class: "secondaryProgress", style: "transform: scaleX(0);" }, progressContainer); const primaryProgress = API.addElement("div", { class: "primaryProgress", style: "transform: scaleX(0);" }, progressContainer); const progressTag = API.addElement("div", { class: "progressTag", style: "display: none;" }, progress, \`
          \${min}
          \${max}
          \`); Object.defineProperties(detail, { "color": { get: () => primaryProgress.style.backgroundColor, set: (v) => primaryProgress.style.backgroundColor = v }, "display": { get: () => progressTag.style.display, set: (v) => progressTag.style.display = v ? "" : "none" }, "max": { get: () => max, set: (v) => { if (v < value || v <= min) return; progressTag.children[1].innerText = max = v; detail.value = value; } }, "min": { get: () => min, set: (v) => { if (v > value || v >= max) return; progressTag.children[0].innerText = min = v; detail.value = value; } }, "nocolor": { get: () => secondaryProgress.style.backgroundColor, set: (v) => secondaryProgress.style.backgroundColor = v }, "value": { get: () => value, set: (v) => { if (v > max || v < min) return; const per = Number(((v - min) / (max - min)).toFixed(3).slice(0, -1)); primaryProgress.style.transform = \`scaleX(\${per})\`; progressContainer.title = (per * 100) + "%"; } } }); min >= max && (min = 0); (value > max || value < min) && (value = 0); detail.min = min, detail.max = max, detail.value = value, detail.color = color, detail.nocolor = nocolor, detail.display = display; return root; } } API.element = ElementModule; API.clickRemove = ClickRemove; //# sourceURL=API://@Bilibili-Old/include/element.js`; /*!***********************!*/ /**/modules["EmbedPlayer.js"] = /*** ./dist/include/EmbedPlayer.js ***/ `class EmbedPlayer { playerParam; playerType; upgrade; callbackFn; flashAddEvents = []; flashRemoveEvents = []; pageno; bofqi = document.querySelector("#bofqi"); get gray_html5() { return !config.noVideo; } set gray_html5(v) { config.noVideo = !v; } /** * 代理EmbedPlayer函数 * @param player "player" * @param swf "//static.hdslb.com/play.swf" * @param playerParams url参数式的播放器初始化参数,需要转化为对象格式才能传递给播放器实例 * @param playerType 播放器类型:flash/HTML5 * @param upgrade 提升播放器版本,可能只在flash格式下有用 * @param callbackFn 初始化播放器后的回调函数 */ constructor(player, swf, playerParams, playerType, upgrade, callbackFn) { this.playerParam = Format.urlObj(\`?\${playerParams}\`); this.playerParam.dashSymbol = true; this.playerParam.aid && Reflect.set(window, "aid", this.playerParam.aid); this.playerParam.cid && Reflect.set(window, "cid", this.playerParam.cid); this.playerType = playerType; this.upgrade = upgrade; this.callbackFn = callbackFn; this.gray_loader(); } /** * 加载外源脚本依赖 * @param src 外源脚本src * @param onload 成功加载后的回调函数 */ loadScript(src, onload) { const script = document.createElement("script"); script.type = "text/javascript"; script.src = src; script.addEventListener("load", () => { script.remove(); onload(); }); script.addEventListener("error", (e) => { script.remove(); toast.error("加载播放器脚本失败!", e.message); }); document.body.appendChild(script); } /** * 初始化HTML5播放器节点 */ loadHtml5Player() { if (!this.bofqi) return debug.warn("页面中并不存在播放器节点!", this.playerParam); if (!window.bilibiliPlayer) { this.loadScript("//static.hdslb.com/player/js/bilibiliPlayer.min.js", () => { this.bofqi.innerHTML = '
          '; window.player = new window.bilibiliPlayer(this.playerParam); this.gray_html5_compatible(); }); } else { this.bofqi.innerHTML = '
          '; window.player = new window.bilibiliPlayer(this.playerParam); this.gray_html5_compatible(); } } eventMaps = { 'jwplayerMediaBuffer': 'video_media_buffer', 'jwplayerMediaBufferFull': 'video_media_buffer_full', 'jwplayerMediaComplete': 'video_media_ended', 'jwplayerMediaError': 'video_media_error', 'jwplayerMediaLoaded': 'video_media_loaded', 'jwplayerMediaMute': 'video_media_mute', 'jwplayerMediaSeek': 'video_media_seek', 'jwplayerMediaTime': 'video_media_time', 'jwplayerMediaVolume': 'video_media_volume' }; apiMaps = { 'mukio_reloadAccess': 'reloadAccess', // 'jwAddEventListener': 'addEventListener', // 'jwRemoveEventListener': 'removeEventListener', 'jwPlay': 'play', 'jwPause': 'pause', 'jwStop': 'stop', 'jwSeek': 'seek', 'jwPlaylistPrev': 'prev', 'jwPlaylistNext': 'next', 'jwGetBuffer': 'getBufferRate', 'jwGetDuration': 'getDuration', 'jwGetFullscreen': 'isFullScreen', 'jwGetWidth': 'getWidth', 'jwGetHeight': 'getHeight', 'jwGetMute': 'isMute', 'jwSetMute': 'setMute', 'jwGetPlaylist': 'getPlaylist', 'jwGetPlaylistIndex': 'getPlaylistIndex', 'jwGetPosition': 'getCurrentTime', 'jwGetState': 'getState', 'jwGetVersion': 'getVersion', 'jwGetVolume': 'volume', 'jwSetVolume': 'volume' }; cElement; /** * 统一HTML5播放器对外接口 */ gray_html5_compatible() { this.cElement = this.bofqi.querySelector("#player_placeholder"); Object.entries(this.apiMaps).forEach(d => { this.cElement[d[0]] = function () { if (window.player && "function" == typeof window.player[d[1]]) { for (var e = arguments.length, t = new Array(e), n = 0; n < e; n++) t[n] = arguments[n]; return window.player[d[1]].apply(window.player, t); } return !1; }; }); Reflect.set(this.cElement, "jwAddEventListener", (type, callback) => { var callbackString = "", _callback; try { "function" != typeof callback && (callbackString = new Function(callback)); } catch (e) { callbackString = function () { }; } this.eventMaps[type] && (_callback = callbackString || callback, window.player && window.player.addEventListener && window.player.addEventListener(this.eventMaps[type], _callback)); }); Reflect.set(this.cElement, "jwRemoveEventListener", (e) => { this.eventMaps[e] && window.player && window.player.removeEventListener && window.player.removeEventListener(this.eventMaps[e]); }); "function" == typeof this.callbackFn && this.cElement.jwAddEventListener("jwplayerMediaLoaded", () => this.callbackFn()); "function" == typeof window.PlayerMediaLoaded && window.PlayerMediaLoaded(); } /** * 检查浏览器flash支持性 * @returns 支持结果 */ flashChecker() { let e = !1, t = 0; if (!!/msie [\\w.]+/.exec(navigator.userAgent.toLowerCase()) && !/Edge/i.test(navigator.userAgent) || /Trident/i.test(navigator.userAgent)) { try { var n = new window.ActiveXObject("ShockwaveFlash.ShockwaveFlash"); if (n) { e = !0; var r = n.GetVariable("\$version"); t = parseInt(r.split(" ")[1].split(",")[0], 10); } } catch (e) { console.error(e); } } else if (navigator.plugins && 0 < navigator.plugins.length) { var i = navigator.plugins["Shockwave Flash"]; if (i) { e = !0; for (var a = i.description.split(" "), o = 0; o < a.length; ++o) isNaN(parseInt(a[o], 10)) || (t = parseInt(a[o], 10)); } } return { hasFlash: e, flashVersion: t }; } /** * 初始化flash播放器节点 */ gray_loader_flash() { // flash播放器已不可用,主动更新全局变量 this.playerParam.aid && (API.aid = this.playerParam.aid); this.playerParam.cid && (API.cid = this.playerParam.cid); this.flashChecker().hasFlash ? window.swfobject && window.swfobject.embedSWF ? this.loadFlashPlayer() : this.loadScript("//static.hdslb.com/js/swfobject.js", () => this.loadFlashPlayer()) : this.getNoFlashTips(); } /** * 不支持flash提示 */ getNoFlashTips() { window.NoFlashTips ? this.createNoFlashTipsInstance() : this.loadScript("//static.hdslb.com/player/noflashtips/no-flash-tips.min.js", () => this.createNoFlashTipsInstance()); } /** * 不支持flash提示内容 */ createNoFlashTipsInstance() { const msg = { backgroundColor: "white", msg: "主人,未安装Flash插件,暂时无法观看视频,您可以…", msgColor: "#000", msgSize: 14, btnList: [ { title: "下载Flash插件", width: 166, height: 40, type: "flash", theme: "white" }, { title: "使用HTML5播放器", width: 166, height: 40, type: "html5", theme: "blue", onClick: (e) => { this.gray_html5 = true, this.loadHtml5Player(), "function" == typeof e && e(); } } ], hasOrText: !1 }; config.noVideo && msg.btnList.push({ title: "下载视频", width: 166, height: 40, type: "download", theme: "red", onClick: (e) => { API.download(); } }); new window.NoFlashTips(this.bofqi, msg); this.bofqi.style.removeProperty("position"); } /** * 加载flash播放器脚本 */ loadFlashPlayer() { this.bofqi.innerHTML = '
          '; window.swfobject.embedSWF(this.upgrade ? "//static.hdslb.com/play_recommend.swf" : "//static.hdslb.com/play.swf", "player_placeholder", "950", "482", "0", "", this.playerParam, { bgcolor: "#ffffff", allowfullscreeninteractive: "true", allowfullscreen: "true", quality: "high", allowscriptaccess: "always", wmode: /Firefox/.test(navigator.userAgent) ? "opaque" : "direct" }, { class: "player" }, () => { "function" == typeof this.callbackFn && this.callbackFn(); "function" == typeof window.PlayerMediaLoaded && window.PlayerMediaLoaded(); this.gray_flash_compatible(); }); } /** * 统一flash播放器对外接口 */ gray_flash_compatible() { this.cElement = this.bofqi.querySelector("#player_placeholder"); window.player = {}; Object.entries(this.apiMaps).forEach(d => { this.cElement[d[0]] = function () { if (window.player && "function" == typeof window.player[d[1]]) { for (var e = arguments.length, t = new Array(e), n = 0; n < e; n++) t[n] = arguments[n]; return window.player[d[1]].apply(window.player, t); } return !1; }; window.player[d[1]] = () => { if (typeof this.cElement[d[0]] === 'function') { return this.cElement[d[0]].apply(this.cElement, arguments); } }; }); Reflect.set(this.cElement, "jwAddEventListener", () => { this.cElement['jwAddEventListener'].apply(this, arguments); }); Reflect.set(this.cElement, "jwRemoveEventListener", (e) => { this.cElement['jwRemoveEventListener'].apply(this, arguments); }); const eventMaps = { 'video_media_buffer': 'jwplayerMediaBuffer', 'video_media_buffer_full': 'jwplayerMediaBufferFull', 'video_media_ended': 'jwplayerMediaComplete', 'video_media_error': 'jwplayerMediaError', 'video_media_loaded': 'jwplayerMediaLoaded', 'video_media_mute': 'jwplayerMediaMute', 'video_media_seek': 'jwplayerMediaSeek', 'video_media_time': 'jwplayerMediaTime', 'video_media_volume': 'jwplayerMediaVolume' }; window.player['addEventListener'] = (type, callback) => { try { if (typeof callback !== 'function') { callback = new Function(callback); } } catch (e) { callback = function () { }; } if (eventMaps[type]) { this.flashAddEvents.push([type, callback]); } }; window.player['removeEventListener'] = (type) => { if (eventMaps[type]) { for (var i = this.flashAddEvents.length - 1; i > 0; i--) { if (this.flashAddEvents[i][0] == type) { this.flashAddEvents.splice(i, 1); } } } }; Object.entries(eventMaps).forEach(d => { this.cElement["jwAddEventListener"](d[1], () => { this.callFunction(d[0]); }); }); } callFunction(type) { const eventMaps = { 'video_media_buffer': 'jwplayerMediaBuffer', 'video_media_buffer_full': 'jwplayerMediaBufferFull', 'video_media_ended': 'jwplayerMediaComplete', 'video_media_error': 'jwplayerMediaError', 'video_media_loaded': 'jwplayerMediaLoaded', 'video_media_mute': 'jwplayerMediaMute', 'video_media_seek': 'jwplayerMediaSeek', 'video_media_time': 'jwplayerMediaTime', 'video_media_volume': 'jwplayerMediaVolume' }; if (eventMaps[type]) { for (var i = 0; i < this.flashAddEvents.length; i++) { this.flashAddEvents[i] && this.flashAddEvents[i][0] == type && this.flashAddEvents[i][1](); } } } /** * 播放器附加菜单 * @param type 菜单类型 * @returns 菜单数据 */ loadExtraMenuConfig(type) { let v = '20161115', exconfig = []; if (type === 'flash' || type === 'flash_gray') { if (this.gray_html5) { exconfig.push({ label: "HTML5播放器", id: "change_h5" }); exconfig.push({ label: "Flash播放器", id: "change_flash", active: true }); } } else { exconfig.push({ label: "HTML5播放器", id: "change_h5", active: true }); exconfig.push({ label: "Flash播放器", id: "change_flash" }); } return { 'ver': v, 'menuItems': exconfig }; } /** * 播放器附加菜单回调函数 * @param id 菜单类型 */ clickMenu(id) { setTimeout(() => { if (id === 'change_h5') { this.gray_html5 = true; this.gray_loader(); } else if (id === 'change_flash') { this.gray_html5 = false; window.player && window.player.destroy && window.player.destroy(); this.gray_loader(); } }); } /** * 根据参数引导播放器类型 */ gray_loader() { this.init_bgray_btn(); ("html5" === this.playerType || this.gray_html5) ? this.loadHtml5Player() : this.gray_loader_flash(); } feedback; init_bgray_btn() { const prt = this.bofqi.parentElement; const gray = API.addElement("div", { class: "bgray-btn-wrap" }, prt); API.addCss(API.getModule("bgray-btn.css") + (prt.classList.contains("movie_play") ? ".movie_play {overflow: visible;} .bgray-btn-wrap {top: -10px;} #bofqi {box-shadow: 0 0 0;}" : "")); API.addElement("div", { class: "bgray-btn show bgray-btn-feedback" }, gray, \`播放
          问题
          反馈\`).addEventListener("click", () => { this.feedback ? this.feedback.show() : window.FeedBackInstance ? (this.feedback = new window.FeedBackInstance(), this.feedback.show()) : (gray.querySelector(".bgray-btn.show").classList.add("player-feedback-disable"), this.loadScript("//static.hdslb.com/player/feedback/feedback.min.js", () => { gray.querySelector(".bgray-btn.show").classList.remove("player-feedback-disable"); this.feedback = window.FeedBackInstance && new window.FeedBackInstance(); this.feedback && this.feedback.show(); })); }); API.addElement("div", { class: "bgray-btn show bgray-btn-help" }, gray, \`帮助\`).addEventListener("click", () => { window.open("//www.bilibili.com/blackboard/help.html#常见播放问题自救方法"); }); } } class GrayManager extends EmbedPlayer { /** * 播放器播放时优先选择的编码、浏览器支持的编码类型 */ codec; constructor(player, swf, playerParams, playerType, upgrade, callbackFn) { super(player, swf, playerParams, playerType, upgrade, callbackFn); let codecId = { "AVC": 7, "HEVC": 12, "AV1": 13 }; this.codec = { preference: codecId[config.codecType], support: {} }; let mime = { "AVC": 'video/mp4;codecs="avc1.640028"', "HEVC": 'video/mp4;codecs="hev1.1.6.L120.90"', "AV1": 'video/mp4;codecs="av01.0.01M.08.0.110.01.01.01.0"' }; for (let i in mime) { this.codec.support[codecId[i]] = MediaSource.isTypeSupported(mime[i]); } location.href.includes("t=") && (this.playerParam.p = this.GetUrlValue("t")); location.href.includes("d=") && (this.playerParam.d = this.GetUrlValue("d")); location.href.includes("lastplaytime=") && (this.playerParam.lastplaytime = this.GetUrlValue("lastplaytime")); } /** * 重新加载播放器实例 * @param playerParams 播放器实例参数,格式同初始化参数 */ reload(playerParams) { if (this.playerParam) { try { window.swfobject && window.swfobject.removeSWF("player_placeholder"), window.player && window.player.pause(), window.player && window.player.destroy && window.player.destroy(), (this.HashManage.get("page") || this.GetUrlValue("p")) && (window.pageno = this.HashManage.get("page") || this.GetUrlValue("p") || 1, this.pageno = window.pageno); } catch (e) { console.log(e); } this.playerParam = Format.urlObj(\`?\${playerParams}\`) || this.playerParam; this.playerParam.dashSymbol = true; this.playerParam && (Reflect.set(window, "aid", this.playerParam.aid), Reflect.set(window, "cid", this.playerParam.cid)); this.gray_loader(); } else window.location.reload(); } /** * 监听url哈希修改 */ HashManage = { p: function (e) { return (this.p = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (e) { return typeof e; } : function (e) { return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e; })(e); }, prependHash: "!", _change: function (e, t) { var n, r = location.hash, i = [], a = "", o = 0, s = {}; r && (r = r.substring(1), this.prependHash && (r = r.replace(new RegExp("^".concat(this.prependHash.replace(/[-[\\]{}()*+?.,\\\\^\$|#\\s]/g, "\\\\\$&"))), ""))), i = r.split("&"); for (var u = 0; u < i.length; u++) { var l = i[u].split("=")[0], d = i[u].split("=")[1]; l && (s[l] = decodeURIComponent(d)); } if ("object" === this.p(e)) { n = Object.keys(e).length; for (var f = 0; f < n; f++) { var c = e[n[f]]; c ? s[n[f]] = encodeURIComponent(c) : !1 === c && delete s[n[f]]; } } else if (t) s[e] = encodeURIComponent(t); else { if (!1 !== t) return void 0 === e ? s : s[e] || null; delete s[e]; } n = Object.keys(s); for (var h = 0; h < n.length; h++) a += 0 !== o ? "&" : this.prependHash, a += "".concat(n[h], "=").concat(s[n[h]]), o += 1; return location.hash = a, s; }, get: function (e) { return this._change(e, null); }, set: function (e, t) { return this._change(e, t); }, clear: function () { location.hash = ""; } }; /** * 从url中提取参数 * @param e 参数名 * @returns 参数值 */ GetUrlValue(e) { var t = new RegExp("(^|&)".concat(e, "=([^&]*)(&|\$)"), "i"), n = window.location.search.substr(1).match(t); if (null != n) try { return decodeURIComponent(n[2]); } catch (e) { return null; } return null; } } API.EmbedPlayer = () => { window.EmbedPlayer = (player, swf, playerParams, playerType, upgrade, callbackFn) => { window.GrayManager = new GrayManager(player, swf, playerParams, playerType, upgrade, callbackFn); }; }; // 托管播放器脚本\`bilibiliPlayer.min.js\` config.trusteeship && API.scriptIntercept("bilibiliPlayer.min.js", undefined, () => { const text = GM.getResourceText("bilibiliPlayer.js"); if (!text) setTimeout(() => { toast.error("bilibiliPlayer.js 资源加载失败!您可以在设置中临时关闭“托管原生脚本”。"); API.displaySetting("trusteeship"); }); return text; }); //# sourceURL=API://@Bilibili-Old/include/EmbedPlayer.js`; /*!***********************!*/ /**/modules["fnval.js"] = /*** ./dist/include/fnval.js ***/ `{ /** * fnval参数标志位 */ class Fnval { MP4 = 1; DASH_H265 = 16; HDR = 64; DASH_4K = 128; DOLBYAUDIO = 256; DOLBYVIDEO = 512; DASH_8K = 1024; DASH_AV1 = 2048; } const fnval = new Fnval(); // 构造播放源请求参数fnval,取当前支持的最大值。 API.fnval = Reflect.ownKeys(fnval).reduce((s, d) => { s += fnval[d]; return s; }, -1); } //# sourceURL=API://@Bilibili-Old/include/fnval.js`; /*!***********************!*/ /**/modules["MediaMeta.js"] = /*** ./dist/include/MediaMeta.js ***/ `{ /** * 置媒体控制器MediaMeta信息 * @param data MediaMeta数据 */ function mediaSession(data) { if (!navigator.mediaSession.metadata) navigator.mediaSession.metadata = new MediaMetadata({ ...data }); else { navigator.mediaSession.metadata.title = data.title; navigator.mediaSession.metadata.artist = data.artist; navigator.mediaSession.metadata.album = data.album; navigator.mediaSession.metadata.artwork = data.artwork; } } API.mediaSession = (data) => mediaSession(data); } //# sourceURL=API://@Bilibili-Old/include/MediaMeta.js`; /*!***********************!*/ /**/modules["nodeObserver.js"] = /*** ./dist/include/nodeObserver.js ***/ `{ const nodelist = []; /** * 注册节点添加监听 * **监听节点变动开销极大,如非必要请改用其他方法并且用后立即销毁!** * @param callback 添加节点后执行的回调函数 * @returns 注册编号,用于使用\`removeObserver\`销毁监听 */ function observerAddedNodes(callback) { try { if (typeof callback === "function") nodelist.push(callback); return nodelist.length - 1; } catch (e) { toast.error("nodeObserver.js", e); } } API.observerAddedNodes = (callback) => observerAddedNodes(callback); /** * 销毁\`observerAddedNodes\`监听 * @param id 注册\`observerAddedNodes\`监听是返回的编号 */ function removeObserver(id) { nodelist.splice(id, 1); } API.removeObserver = (id) => removeObserver(id); (new MutationObserver(d => d.forEach(d => { d.addedNodes[0] && nodelist.forEach(async (f) => { try { f(d.addedNodes[0]); } catch (e) { debug.error(d); debug.error(e); } }); }))).observe(document, { childList: true, subtree: true }); } //# sourceURL=API://@Bilibili-Old/include/nodeObserver.js`; /*!***********************!*/ /**/modules["rebuildPlayerurl.js"] = /*** ./dist/include/rebuildPlayerurl.js ***/ `class RebuildPlayerurl { static OBJ = {}; playurl = { accept_description: ["高清 1080P+", "高清 1080P", "高清 720P", "清晰 480P", "流畅 360P"], accept_format: "hdflv2,flv,flv720,flv480,mp4", accept_quality: [112, 80, 64, 32, 16], bp: 0, code: 0, dash: { audio: [], dolby: { audio: [], type: "NONE" }, duration: 0, min_buffer_time: 1.5, minBufferTime: 1.5, video: [] }, fnval: 0, fnver: 0, format: "flv480", from: "local", has_paid: false, is_preview: 0, message: "", no_rexcode: 1, quality: 32, result: "suee", seek_param: "start", seek_type: "offset", status: 2, support_formats: [ { description: "高清 1080P+", display_desc: "1080P", format: "hdflv2", need_login: true, need_vip: true, new_description: "1080P 高码率", quality: 112, superscript: "高码率" }, { description: "高清 1080P", display_desc: "1080P", format: "flv", need_login: true, new_description: "1080P 高清", quality: 80, superscript: "" }, { description: "高清 720P", display_desc: "720P", format: "flv720", need_login: true, new_description: "720P 高清", quality: 64, superscript: "" }, { description: "清晰 480P", display_desc: "480P", format: "flv480", new_description: "480P 清晰", quality: 32, superscript: "" }, { description: "流畅 360P", display_desc: "360P", format: "mp4", new_description: "360P 流畅", quality: 16, superscript: "" } ], timelength: 0, type: "DASH", video_codecid: 7, video_project: true }; codecs = { default: { 30112: 'avc1.640028', 30102: 'hev1.1.6.L120.90', 30080: 'avc1.640028', 30077: 'hev1.1.6.L120.90', 30064: 'avc1.64001F', 30066: 'hev1.1.6.L120.90', 30032: 'avc1.64001E', 30033: 'hev1.1.6.L120.90', 30011: 'hev1.1.6.L120.90', 30016: 'avc1.64001E', 30280: 'mp4a.40.2', 30232: 'mp4a.40.2', 30216: 'mp4a.40.2', // 低码音频 }, app: { 30016: 'avc1.64001E', 30032: 'avc1.64001F', 30064: 'avc1.640028', 30080: 'avc1.640032', 30216: 'mp4a.40.2', 30232: 'mp4a.40.2', 30280: 'mp4a.40.2' // APP源 高码音频 } }; frameRate = { 30112: '16000/672', 30102: '16000/672', 30080: '16000/672', 30077: '16000/656', 30064: '16000/672', 30066: '16000/656', 30032: '16000/672', 30033: '16000/656', 30011: '16000/656', 30016: '16000/672' }; resolution = { 30112: [1920, 1080], 30102: [1920, 1080], 30080: [1920, 1080], 30077: [1920, 1080], 30064: [1280, 720], 30066: [1280, 720], 30032: [852, 480], 30033: [852, 480], 30011: [640, 360], 30016: [640, 360], // 360P }; /** * 获取链接ids * @param url 下载链接 * @param duration 媒体时长 */ getIdxs(url, duration) { let range = Math.round(duration * 3.5); range = range < 6000 ? 6000 : range; return xhr({ url: url, responseType: 'arraybuffer', headers: { 'Range': \`bytes=0-\${range}\` }, credentials: false }); } /** * 过滤问题音频 * @param audio 音频数据数组 */ fixAudio(audio) { return audio.reduce((arr, d) => { if (d.id == 30232 || d.id == 30280 || d.id == 30216) arr.push(d); return arr; }, []); } /** * 重构APP端数据 * @param app 原始数据对象 */ async appPlayurl(app) { if (app.durl) return app; if (app.dash.duration) { app.dash.audio = this.fixAudio(app.dash.audio); return app; } toast("重构DASH数据中..."); for (let key in app) this.playurl[key] = app[key]; // duration向上取整 this.playurl.dash.duration = Math.ceil(app.timelength / 1000); this.playurl.dash.minBufferTime = this.playurl.dash.min_buffer_time = 1.5; // 构造Promise序列以同时获取所有DASH媒体segment数据 // 本应由播放器自行获取,B站官方称之为【首帧优化】却在缺失时直接报错导致播放器无法正常载入视频 let arr = []; this.playurl.dash.video.forEach((d, i, e) => { arr.push((async (d) => { RebuildPlayerurl.OBJ["sidx" + String(API.cid)] = RebuildPlayerurl.OBJ["sidx" + String(API.cid)] || {}; let id = d.base_url.match(/[0-9]+\\.m4s/)[0].split(".")[0]; if (d.SegmentBase) RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id] = [d.SegmentBase.Initialization, d.SegmentBase.indexRange]; if (!RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id]) { let data = new Uint8Array(await this.getIdxs(d.base_url, this.playurl.dash.duration)); let hex_data = Array.prototype.map.call(data, x => ('00' + x.toString(16)).slice(-2)).join(''); // 首个“sidx”出现4字节之前的部分为索引起始点 let indexRangeStart = hex_data.indexOf('73696478') / 2 - 4; // 首个“mooc”出现前5字节结束索引 let indexRagneEnd = hex_data.indexOf('6d6f6f66') / 2 - 5; // 挂载到BLOD下,切换清晰度直接继承使用(以cid为切p标记) RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id] = ['0-' + String(indexRangeStart - 1), String(indexRangeStart) + '-' + String(indexRagneEnd)]; debug("DASH-video:", id, RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id]); } d.segment_base = { initialization: RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id][0], index_range: RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id][1] }; d.SegmentBase = { Initialization: RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id][0], indexRange: RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id][1] }; d.backupUrl = d.backup_url = d.backupUrl || d.backup_url || []; d.baseUrl = d.base_url; d.codecs = d.codecs || this.codecs.app[id] || this.codecs.default[id]; d.frameRate = d.frame_rate = d.frameRate || d.frame_rate || this.frameRate[id]; d.height = d.height || this.resolution[id][1]; d.width = d.width || this.resolution[id][0]; d.mimeType = d.mime_type = d.mimeType || d.mime_type || 'video/mp4'; d.sar = d.sar || "1:1"; d.startWithSAP = d.start_with_sap = d.startWithSAP || d.start_with_sap || 1; })(e[i])); }); this.playurl.dash.audio = this.fixAudio(this.playurl.dash.audio); this.playurl.dash.audio.forEach((d, i, e) => { arr.push((async (d) => { RebuildPlayerurl.OBJ["sidx" + String(API.cid)] = RebuildPlayerurl.OBJ["sidx" + String(API.cid)] || {}; let id = d.base_url.match(/[0-9]+\\.m4s/)[0].split(".")[0]; if (d.SegmentBase) RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id] = [d.SegmentBase.Initialization, d.SegmentBase.indexRange]; if (!RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id]) { let data = new Uint8Array(await this.getIdxs(d.base_url, this.playurl.dash.duration)); let hex_data = Array.prototype.map.call(data, x => ('00' + x.toString(16)).slice(-2)).join(''); let indexRangeStart = hex_data.indexOf('73696478') / 2 - 4; let indexRagneEnd = hex_data.indexOf('6d6f6f66') / 2 - 5; RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id] = ['0-' + String(indexRangeStart - 1), String(indexRangeStart) + '-' + String(indexRagneEnd)]; debug("DASH-audio:", id, RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id]); } d.segment_base = { initialization: RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id][0], index_range: RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id][1] }; d.SegmentBase = { Initialization: RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id][0], indexRange: RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id][1] }; d.backupUrl = d.backup_url = d.backupUrl || d.backup_url || []; d.baseUrl = d.base_url; d.codecs = d.codecs || this.codecs.app[id] || this.codecs.default[id] || "mp4a.40.2"; d.mimeType = d.mime_type = d.mimeType || d.mime_type || 'audio/mp4'; })(e[i])); }); toast("等待数据回传..."); if (arr[0]) await Promise.all(arr); // video排序 let avc = [], hev = [], video = []; this.playurl.dash.video.forEach((d) => { if (d.codecid == 7) avc.push(d); else hev.push(d); }); let length = avc.length > hev.length ? avc.length : hev.length; for (let i = length - 1; i >= 0; i--) { if (avc[i]) video.push(avc[i]); if (hev[i]) video.push(hev[i]); } this.playurl.dash.video = video; toast.success("DASH数据重构成功!", "正在投喂给播放器..."); debug.log(this.playurl); return this.playurl; } /** * 重构Thailand数据 * @param ogv 原始数据 */ async ogvPlayurl(ogv) { toast("重构DASH数据中..."); this.playurl.quality = ogv.data.video_info.quality; let num = this.playurl.accept_quality.indexOf(this.playurl.quality); this.playurl.format = this.playurl.accept_format.split(",")[num]; this.playurl.timelength = ogv.data.video_info.timelength; this.playurl.accept_quality.splice(0, num); this.playurl.support_formats.splice(0, num); this.playurl.accept_description.splice(0, num); this.playurl.accept_format = this.playurl.accept_format.split(","); this.playurl.accept_format.splice(0, num); this.playurl.accept_format = this.playurl.accept_format.join(","); this.playurl.dash.duration = Math.ceil(this.playurl.timelength / 1000); this.playurl.dash.minBufferTime = this.playurl.dash.min_buffer_time = 1.5; let arr = []; ogv.data.video_info.stream_list.forEach((d) => { if (d.dash_video && d.dash_video.base_url) { arr.push((async (d) => { RebuildPlayerurl.OBJ["sidx" + String(API.cid)] = RebuildPlayerurl.OBJ["sidx" + String(API.cid)] || {}; let id = d.dash_video.base_url.match(/[0-9]+\\.m4s/)[0].split(".")[0]; if (!RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id]) { let data = new Uint8Array(await this.getIdxs(d.dash_video.base_url, this.playurl.dash.duration)); let hex_data = Array.prototype.map.call(data, x => ('00' + x.toString(16)).slice(-2)).join(''); let indexRangeStart = hex_data.indexOf('73696478') / 2 - 4; let indexRagneEnd = hex_data.indexOf('6d6f6f66') / 2 - 5; RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id] = ['0-' + String(indexRangeStart - 1), String(indexRangeStart) + '-' + String(indexRagneEnd)]; debug("DASH-video:", id, RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id]); } this.playurl.dash.video.push({ SegmentBase: { Initialization: RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id][0], indexRange: RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id][1] }, segment_base: { initialization: RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id][0], index_range: RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id][1] }, backupUrl: [], backup_url: [], bandwidth: d.dash_video.bandwidth, baseUrl: d.dash_video.base_url, base_url: d.dash_video.base_url, codecid: d.dash_video.codecid, codecs: this.codecs.app[id] || this.codecs.default[id], frameRate: this.frameRate[id], frame_rate: this.frameRate[id], height: this.resolution[id][1], id: d.stream_info.quality, md5: d.dash_video.md5, mimeType: "video/mp4", mime_type: "video/mp4", sar: "1:1", size: d.dash_video.size, startWithSAP: 1, start_with_sap: 1, width: this.resolution[id][0] }); })(d)); } })(ogv.data.video_info.dash_audio).forEach((d) => { arr.push((async (d) => { RebuildPlayerurl.OBJ["sidx" + String(API.cid)] = RebuildPlayerurl.OBJ["sidx" + String(API.cid)] || {}; let id = d.base_url.match(/[0-9]+\\.m4s/)[0].split(".")[0]; if (!RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id]) { let data = new Uint8Array(await this.getIdxs(d.base_url, this.playurl.dash.duration)); let hex_data = Array.prototype.map.call(data, x => ('00' + x.toString(16)).slice(-2)).join(''); let indexRangeStart = hex_data.indexOf('73696478') / 2 - 4; let indexRagneEnd = hex_data.indexOf('6d6f6f66') / 2 - 5; RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id] = ['0-' + String(indexRangeStart - 1), String(indexRangeStart) + '-' + String(indexRagneEnd)]; debug("DASH-audio:", id, RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id]); } this.playurl.dash.audio.push({ SegmentBase: { Initialization: RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id][0], indexRange: RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id][1] }, segment_base: { initialization: RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id][0], index_range: RebuildPlayerurl.OBJ["sidx" + String(API.cid)][id][1] }, backupUrl: [], backup_url: [], bandwidth: d.bandwidth, baseUrl: d.base_url, base_url: d.base_url, codecid: d.codecid, codecs: this.codecs.app[id] || this.codecs.default[id], frameRate: "", frame_rate: "", height: 0, id: id, md5: d.md5, mimeType: "audio/mp4", mime_type: "audio/mp4", sar: "", size: d.size, startWithSAP: 0, start_with_sap: 0, width: 0 }); })(d)); }); toast("等待数据回传..."); await Promise.all(arr); toast.success("DASH数据重构成功!", "正在投喂给播放器..."); debug.log(this.playurl); return this.playurl; } } API.rebuildPlayerurl = RebuildPlayerurl; //# sourceURL=API://@Bilibili-Old/include/rebuildPlayerurl.js`; /*!***********************!*/ /**/modules["rewrite.js"] = /*** ./dist/include/rewrite.js ***/ `class Rewrite { url = new URL(location.href); __INITIAL_STATE__ = {}; /** * 旧版脚本序列,初始化请复制给\`scripts\`! */ script = []; /** * 重写页面前需要清理的全局变量污染 */ dush = [ // "__INITIAL_STATE__", "__PGC_USERSTATE__", "__BILI_CONFIG__", "Sentry", "__mobxGlobals", "__mobxInstanceCount", "_babelPolyfill", "BilibiliPlayer", "BiliJsBridge", "LazyLoad", "lazyload", "regeneratorRuntime", "ownKeys", "asyncGeneratorStep", "Bjax", "BPlayer", "BwpElement", "BwpMediaSource", "bbComment", "bPlayer", "EmbedPlayer", "GrayManager", "PlayerAgent", "PlayerSetOnline", "abtest", "ad_rp", "ad_url", "bPlayer", "bsourceFrom", "dashjs", "deltaFilter", "directiveDispatcher", "ep", "flashChecker", "flvjs", "getAuthorInfo", "getCookie", "getIEVersion", "gqs", "heimu", "insertLink", "insertScript", "iris", "isBiliPlayer", "isEmbedPlayer", "isInit", "jsurl", "jsUrls", "loadLink", "loadScript", "loginInfoCallbacks", "md", "nano", "nanoWidgetsJsonp", "player", "playerInfo", "player_fullwin", "player_widewin", "rec_rp", "regeneratorRuntime", "reportConfig", "reportFistAdFs", "reportObserver", "setSize", "setSizeStyle", "spmReportData", "vd", "videoWidgetsJsonP", "webAbTest", "webpackJsonp", "__getClientLogo", "_arrayLikeToArray", "_arrayWithHoles", "_arrayWithoutHoles", "_asyncToGenerator2", "_classCallCheck", "_createClass", "_createForOfIteratorHelper", "_defineProperties", "_defineProperty", "_iterableToArray", "_iterableToArrayLimit", "_nonIterableRest", "_nonIterableSpread", "_objectSpread", "_slicedToArray", "_toConsumableArray", "_typeof", "_unsupportedIterableToArray", "el", "BiliCm", "BiliHeader", "webpackJsonpwebpackLogReporter", "webpackLogReporter", "core", "__getClientLogo", "_arrayLikeToArray", "_arrayWithoutHoles", "_iterableToArray", "_nonIterableSpread", "_toConsumableArray", "_unsupportedIterableToArray", "AttentionList", "UserStatus", "biliQuickLogin", "clearImmediate", "jvsCert", "loadLoginStatus", "mOxie", "moxie", "o", "onLoginInfoLoaded", "plupload", "recaptcha", "setImmediate", "setTid", "show1080p", "showCoopModal", "showPay", "swfobject", "tabSocket", "__BiliUser__", "___grecaptcha_cfg", "__core-js_shared__", ]; /** * 旧版网页框架 * **只在重写页面之外可用!** */ Dom; /** * 重写完页面执行的回调函数 */ loadendCallback = []; cleard = false; title = document.title; /** * 添加重写完页面执行的回调函数 */ set onload(v) { this.loadendCallback.push(v); } /** * 重写页面工具 * 请继承本接口并定义对应页面专属属性和方法。 * 1. 在modules接口中拓展旧版网页框架名并于html目录下准备好网页框架(剔除所有script标签)。 * 2. 将所有剔除的script**严格依次**以属性键值对像添加进script数组中,内联脚本文本属性名为\`text\`。 * 3. 部分页面需要构造\`__INITIAL_STATE__\`数据,请在重构页面(\`flushDocument\`)前准备好并写入window变量下。 * 5. 需要页面重构完再执行的回调函数请复制给\`onload\`属性,可以添加多个,不会相互覆盖,且异步并行回调。 * 6. 重写页面要异步等待外源脚本加载完,完成后推送\`load\`\`DOMContentLoaded\`等标准事件。 * @param 旧版网页框架名,**请移除其中的script标签** */ constructor(html) { if (config.compatible === "极端") { GM.DOM.write(API.getModule(html)); GM.DOM.close(); } else { config.compatible === "默认" && window.stop(); document.replaceChild(document.implementation.createDocumentType('html', '', ''), document.doctype); document.documentElement.replaceWith((new DOMParser().parseFromString(API.getModule(html), 'text/html')).documentElement); } (!this.title.includes("出错")) && (document.title = this.title); this.restorePlayerSetting(); API.switchVideo(() => this.setActionHandler()); } /** * 修复播放器设置 * 新版播放器修改过播放器设置,这会导致旧版播放器设置读取异常。 */ async restorePlayerSetting() { let bilibili_player_settings = localStorage.getItem("bilibili_player_settings"); let settings_copy = GM.getValue("bilibili_player_settings", {}); if (bilibili_player_settings) { let settings = JSON.parse(bilibili_player_settings); if (settings?.video_status?.autopart !== "") GM.setValue("bilibili_player_settings", settings); else if (settings_copy) localStorage.setItem("bilibili_player_settings", JSON.stringify(settings_copy)); } else if (settings_copy) { localStorage.setItem("bilibili_player_settings", JSON.stringify(settings_copy)); } } /** * 清洗页面及全局变量 */ clearWindow() { this.cleard = true; this.dush.forEach(d => { try { window[d] = undefined; } catch (e) { debug(d); } }); API.EmbedPlayer(); } /** * 刷新页面 * 将进入脚本插入循环,页面重构完成请通过\`onload\`属性回调 */ flushDocument() { !this.cleard && this.clearWindow(); !(this.script.length === 0) ? this.loadScript(this.script[0]) : this.loadenEvent(); } /** * 脚本插入循环 * @param obj 脚本属性数据 */ loadScript(obj) { if (obj.defer) { // defer脚本重新追加向最后 const temp = this.script.shift(); delete obj.defer; this.script.push(temp); return this.flushDocument(); } const script = document.createElement("script"); if (obj.text) { // 内联脚本 script.text = obj.text; delete obj.text; } if (obj.src) { // 外源脚本需等待返回 script.addEventListener("load", () => { this.script.shift(); this.flushDocument(); }); script.addEventListener("error", () => { this.script.shift(); this.flushDocument(); }); } Object.entries(obj).forEach(d => { script.setAttribute(d[0], d[1]); }); document.body.appendChild(script); if (!obj.src) { // 非外源脚本立刻返回 this.script.shift(); this.flushDocument(); } } /** * 重写完信息通知 */ loadenEvent() { this.loadendCallback.forEach(async (d) => d()); if (config.compatible === "默认") { document.dispatchEvent(new ProgressEvent("readystatechange")); document.dispatchEvent(new ProgressEvent("DOMContentLoaded")); window.dispatchEvent(new ProgressEvent("DOMContentLoaded")); window.dispatchEvent(new ProgressEvent("load")); } } /** * 添加媒体控制 */ setActionHandler() { navigator.mediaSession.setActionHandler('play', () => window.player.play()); navigator.mediaSession.setActionHandler('pause', () => window.player.pause()); navigator.mediaSession.setActionHandler('seekbackward', () => window.player.seek(window.player.getCurrentTime() - 10)); navigator.mediaSession.setActionHandler('seekforward', () => window.player.seek(window.player.getCurrentTime() + 10)); navigator.mediaSession.setActionHandler('previoustrack', () => window.player.prev()); navigator.mediaSession.setActionHandler('nexttrack', () => window.player.next()); } /** * 临时禁用重写并跳转回新版页面 */ stop(reason) { sessionStorage.setItem("disable_rewrite", reason); location.reload(); } } API.rewrite = Rewrite; //# sourceURL=API://@Bilibili-Old/include/rewrite.js`; /*!***********************!*/ /**/modules["setting.js"] = /*** ./dist/include/setting.js ***/ `{ // 注册设置菜单 API.registerMenu({ key: "common", name: "通用", svg: '' }); API.registerMenu({ key: "rewrite", name: "重构", svg: \`\` }); API.registerMenu({ key: "restore", name: "修复", svg: \`\` }); API.registerMenu({ key: "style", name: "样式", svg: \`\` }); API.registerMenu({ key: "danmaku", name: "弹幕", svg: \`\` }); API.registerMenu({ key: "player", name: "播放", svg: \`\` }); API.registerMenu({ key: "live", name: "直播", svg: \`\` }); API.registerMenu({ key: "download", name: "下载", svg: \`\` }); // 注册设置项 API.registerSetting({ key: "developer", sort: "common", label: "开发者模式", svg: '', type: "switch", value: false, float: '开发者模式将暴露核心变量 API 到页面顶级对象 window,可以借此在控制台调试部分功能。', sub: '暴露 API 到 window', action: (value) => { value ? (!window.API && (window.API = API)) : (window.API && delete window.API); } }); API.registerSetting({ key: "trusteeship", sort: "common", label: "托管原生脚本", svg: '', type: "switch", value: true, float: "脚本修改了部分B站原生脚本以解决常规手段无法解决的问题,但由于托管CDN没有国内节点等原因可能访问不畅,如果出现页面其他情况都正常唯独播放器加载不出来的情况可以尝试开启。关闭本选项将导致部分功能不可用,如非必要请勿关闭!", sub: "代为修复和维护" }); config.developer && (window.API = API); API.registerSetting({ key: "compatible", sort: "common", label: "页面重构模式", svg: \`\`, type: "row", sub: "页面不正常时的选择", value: "默认", list: ["极端", "默认", "兼容"], float: \`“默认”模式下会中止默认DOM树的解析,更有效地保障旧版页面不被新版脚本破坏,但可能引发部分浏览器扩展(如pakku.js)功能异常。
          “兼容”模式可改善这一问题,但加剧了旧版页面被破坏的可能性。
          另有“极端”模式,恢复经典的“重写”模式,此模式恢复的页面稳定性最佳,但与其他脚本或浏览器扩展兼容性最差,任何在本脚本之前或与本脚本同时注入页面的脚本或浏览器扩展的"content.js"功能都受到影响。
          很抱歉还是没能找到两全的办法,请自行按需调整。\` }); API.registerSetting({ key: "av", sort: "rewrite", label: "av/BV", type: "switch", value: true, float: '重构以恢复旧版av视频播放页。' }); API.registerSetting({ key: "upList", sort: "style", label: "UP主列表", sub: "展示视频合作者", type: "switch", value: false }); API.registerSetting({ key: "electric", sort: "player", label: "跳过充电鸣谢", sub: "在视频末尾", type: "switch", value: false }); API.registerSetting({ key: "enlike", sort: "player", label: "添加点赞功能", sub: "自制、简陋", type: "switch", value: false, float: "旧版播放器的时代点赞功能还未存在,本脚本代为设计了个丑丑的点赞功能。注意对于bangumi,点赞数据计算的是单P的。" }); API.registerSetting({ key: "medialist", sort: "rewrite", label: "medialist", type: "switch", value: true, float: "用旧版av页重构medialist页面。该页面使用曾经的播单页面进行模拟,初始状态视频数据为20,你可以滚送到播单底部以动态加载更多。另外由于播单已被官方禁用,您无法对播单进行收藏等操作,也不能访问播单详情页面。" }); API.registerSetting({ type: "switch", key: "index", label: "主页", value: true, sort: "rewrite", float: '重构以恢复旧版主页' }); API.registerSetting({ type: "switch", key: "indexLoc", label: "过滤主页广告", sub: "banner+recommand", value: false, sort: "style", float: '当然指的是旧版主页。' }); API.registerSetting({ type: "switch", key: "privateRecommend", label: "禁用主页个性化推荐", sub: "还是习惯全站统一推荐", value: false, sort: "style", float: '禁用旧版主页banner右边的个性化推荐,恢复全站统一推荐。' }); API.registerSetting({ key: "protoDm", sort: "danmaku", label: "启用新版弹幕", sub: "proto弹幕", type: "switch", value: true, float: \`添加旧版播放器新版proto弹幕支持。由于旧版xml弹幕已获取不到90分钟后的弹幕,本功能不建议禁用。
          ”\` }); API.registerSetting({ key: "commandDm", sort: "danmaku", label: "添加互动弹幕", sub: "投票弹窗等", type: "switch", value: false, float: \`可以使用新版的一些弹窗互动组件。目前可用组件:评分弹窗、投屏弹窗、关联视频跳转按钮、带“UP主”标识弹幕。
          需要同时开启新版proto弹幕。\` }); API.registerSetting({ key: "logReport", sort: "common", label: "日志拦截", svg: '', sub: "拦截B站日志上报", float: "网页端日志采集太频繁,稍微动下鼠标都要发送数条日志请求,给network调试带来额外的困扰。", type: "switch", value: false }); API.registerSetting({ key: "heartbeat", sort: "restore", label: "修复视频心跳", sub: "出现不记录播放历史症状时的选择", float: "尝试修复可能被广告拦截扩展误伤的视频心跳。", type: "switch", value: false }); API.registerSetting({ key: "noVideo", sort: "player", label: "flash播放器", sub: "可用于临时不加载视频进入视频页面", float: "临时启用flash播放器以拦截播放器载入,如需下载视频可切换到“下载”标签呼出下载面板,恢复播放器请点击HTML5按钮或在设置中关闭本功能。", type: "switch", value: false }); API.registerSetting({ key: "bannerGif", sort: "style", label: "丰富顶栏动图", sub: '搜索框下gif', float: "替换顶栏动图接口,避免单调。", type: "switch", value: true }); API.registerSetting({ key: "danmakuFirst", sort: "style", label: "自动切换到弹幕列表", sub: "默认是展示推荐视频", float: "自动从推荐视频切换到播放弹幕列表。", type: "switch", value: false }); API.registerSetting({ type: "sort", key: "autoDo", label: "自动化操作", sort: "player", sub: "进入播放页面及切P时", list: [{ key: "showBofqi", sort: "style", label: "自动滚动到播放器", type: "switch", value: false }, { key: "screenWide", sort: "style", label: "自动宽屏", type: "switch", value: false, action: v => v && (config.webFullScreen = false) }, { key: "noDanmaku", sort: "style", label: "自动关弹幕", type: "switch", value: false }, { key: "autoPlay", sort: "style", label: "自动播放", type: "switch", value: false }, { key: "webFullScreen", sort: "style", label: "自动网页全屏", type: "switch", value: false, action: v => v && (config.screenWide = false) }] }); API.registerSetting({ key: "segProgress", sort: "player", label: "分段进度条", sub: "仅限看点视频", type: "switch", value: false }); API.registerSetting({ key: "replyList", sort: "style", label: "恢复评论翻页", sub: "可以选择跳转而不必一直下拉", type: "switch", value: true, float: '恢复旧版翻页评论区。
          重构过的页面除外,那些默认就是翻页评论区。' }); API.registerSetting({ key: "section", sort: "style", label: "统一换回旧版顶栏", sub: "针对未重构的页面", type: "switch", value: true, float: '非重构页面顶栏底栏也替换为旧版。' }); API.registerSetting({ key: "concatDanmaku", sort: "danmaku", label: "合并载入弹幕", sub: "本地弹幕/在线弹幕", type: "switch", value: false, float: '载入本地弹幕文件或者在线弹幕时是否与播放器当前弹幕合并。' }); API.registerSetting({ key: "danmakuHashId", sort: "danmaku", label: "反查弹幕发送者", sub: "结果仅供参考!", type: "switch", value: false, float: '旧版播放器上右键弹幕将显示弹幕发送者。
          ※ 使用哈希逆向算法,存在碰撞可能性,所示信息仅供参考,或者干脆查不出来。' }); API.registerSetting({ type: "switch", key: "errands", label: '恢复对于番剧出差DM組的访问', sub: '还好没赶尽杀绝', value: true, sort: "restore", float: '使用备份数据修复对于番剧出差官方空间的访问。' }); API.registerSetting({ type: "switch", key: "album", label: "还原个人空间相簿链接", sub: "相簿比动态页面好看", value: false, sort: "restore", float: '将个人空间的相簿链接从动态重定向回原来的相簿。' }); API.registerSetting({ type: "switch", key: "jointime", label: "显示账号注册时间", sub: "历史不该被隐藏", value: false, sort: "restore", float: '在空间显示对应账号的注册时间。' }); API.registerSetting({ key: "lostVideo", sort: "restore", label: "修复失效视频信息", sub: \`有些甚至评论还在!\`, type: "switch", value: false, float: '使用第三方数据修复收藏、频道等处的失效视频信息。(以红色删除线标记)
          访问失效视频链接时将尝试重建av页面。
          ※ 依赖第三方数据库且未必有效,请谨慎考虑是否开启!' }); API.registerSetting({ key: "carousel", sort: "restore", label: "修复播放器消息", sub: "新番消息", type: "switch", value: true, float: '使用新番推荐修复播放器顶部的消息通知。' }); API.registerSetting({ key: "bangumi", sort: "rewrite", label: "bangumi", sub: "ss/ep", type: "switch", value: true, float: '重构以恢复旧版bangumi播放页。' }); API.registerSetting({ key: "limit", sort: "player", label: "解除区域/平台限制", sub: "港澳台?泰版?仅限APP?", float: "同类功能脚本可能会冲突,使用专用脚本切莫开启本功能!", type: "sort", list: [ { key: "videoLimit", sort: "player", label: "解除限制", type: "switch", value: false, sub: "区域+APP" }, { key: "limitAccesskey", sort: "player", label: "账户授权", sub: "泰区除外", type: "action", title: "管理", action: () => { API.importModule("accesskey.js"); } }, { key: "limitServer", sort: "player", label: "泰区代理", type: "input", value: "https://api.global.bilibili.com", float: "泰区番剧限制需要自备相应的代理服务器(需要https协议头但无需末尾的斜杠!)
          中文域名请先使用punycode转化一下。
          本功能由于缺乏调试条件维护不善请多担待!", input: { type: "url", placeholder: "URL" }, pattern: /(\\w+):\\/\\/([^/:]+)(:\\d*)?([^# ]*)/ } ] }); API.registerSetting({ key: "bangumiEplist", sort: "player", label: "保留番剧回目列表", sub: "牺牲特殊背景图", type: "switch", value: false, float: '部分带特殊背景图片的番剧会隐藏播放器下方的番剧回目列表,二者不可得兼,只能选一。' }); API.registerSetting({ key: "episodeData", sort: "style", label: "显示番剧分集数据", sub: "原本是合集数据", type: "switch", value: false, float: '有分集数据时将bangumi播放、弹幕数替换为当集数据。原合集数据将显示在鼠标焦点信息上。' }); API.registerSetting({ type: "switch", key: "watchlater", label: "稍后再看", value: true, sort: "rewrite", float: '重构以恢复旧版稍后再看。' }); API.registerSetting({ type: "switch", key: "history", label: "只显示视频历史", sub: "去除专栏、直播记录", value: false, sort: "style" }); API.registerSetting({ type: "switch", key: "searchHistory", label: "去除历史记录页面搜索框", sub: "其实留着也没什么", value: false, sort: "style" }); API.registerSetting({ type: "switch", key: "liveP2p", label: "禁止P2P上传", sub: "小水管禁不起别人白嫖!", value: true, sort: "live", float: "禁止直播间使用WebRTC进行P2P共享上传,以免暴露ip地址,并为小水管节约带宽。" }); API.registerSetting({ type: "switch", key: "sleepCheck", label: "禁止挂机检测", sub: "就喜欢挂后台听个响不行吗!", value: true, sort: "live", float: "禁止直播间5分钟不操作判定挂机并切断直播,可以放心挂后台听个响。" }); API.registerSetting({ type: "switch", key: "player", label: "嵌入", value: true, sort: "rewrite", float: '重构以恢复旧版嵌入播放器。' }); API.registerSetting({ type: "switch", key: "ranking", label: "排行榜", value: true, sort: "rewrite", float: "重构以恢复旧版全站排行榜。" }); API.registerSetting({ type: "switch", key: "read", label: "专栏", value: true, sort: "rewrite", float: "重构以启用旧版专栏。" }); API.registerSetting({ type: "switch", key: "unloginPopover", label: "移除未登录弹窗", sub: "有些时候就是不喜欢登录", value: false, sort: "style" }); API.registerSetting({ key: "downloadPicture", type: "picture", sort: "download", src: '//s2.hdslb.com/bfs/static/blive/blfe-album-detail/static/img/empty-hint.7b606b9.jpg', hidden: !API.aid, callback: function () { API.aid && API.getAidInfo(API.aid).then(d => { this.innerHTML = \`\`; }); } }); API.runWhile(() => API.aid, () => { API.changeSettingMode({ downloadPicture: false }); }); API.registerSetting({ type: "action", key: "downloadThis", label: "下载面版", title: "呼出", sub: "只在视频页面有效", sort: "download", disabled: 0, action: () => { if (API.aid && API.cid) { API.download(); } else toast.warning("当前并非视频页,请在视频页面打开!"); } }); API.registerSetting({ type: "switch", sort: "download", key: "downloadContentmenu", label: "右键菜单", sub: "播放画面上右键添加下载菜单", value: false }); API.registerSetting({ type: "mutlti", sort: "download", key: "downloadList", label: "视频类型", sub: "右键呼出下载时请求的类型", value: ["mp4", "dash", "flv"], list: ["mp4", "dash", "flv"], float: '下载功能会自动读取播放器已载入的视频源并呈现在下载面板上,即使未勾选对应的视频类型。
          勾选了也不一定能获取到该类型的视频源。' }); API.registerSetting({ type: "row", sort: "download", key: "downloadQn", label: "默认画质", sub: "针对flv格式", value: 127, list: ["0", 15, 16, 32, 48, 64, 74, 80, 112, 116, 120, 125, 126, 127], float: '画质qn参数,数值越大画质越高,0表示自动。64(720P)以上需要登录,112(1080P+)以上需要大会员。一般只需设置为最大即可,会自动获取到能获取的最高画质。' }); API.registerSetting({ type: "switch", sort: "download", key: "TVresource", label: "请求TV源", sub: "无水印", value: false, float: \`请求TV端的视频源,该端口可以获取到无水印的视频源(mp4格式除外),
          此类源无法以“右键保存”方式下载,请改用ef2或者aria2,且“referer”选项必须置空!
          大会员专享类视频下载将要求电视端大会员,与一般大会员不互通。授权大会员状态请尝试设置-播放-解除区域/平台限制-账户授权(有效性待测!)\` }); API.registerSetting({ type: "row", sort: "download", key: "downloadMethod", label: "下载方式", value: "右键保存", list: ["右键保存", "ef2", "aria2", "aira2 RPC"], action: (v) => { switch (v) { case "ef2": API.alertMessage(\`EF2是作者开发的一款从浏览器中拉起IDM进行下载的中间软件,可以非常方便地传递下载数据给IDM,并支持自定义文件名、保存目录等。您必须安装了ef2和IDM才能使用本方式!\`).then(d => { d ? API.changeSettingMode({ referer: false, useragent: false, filepath: false, IDMLater: false, IDMToast: false, rpcServer: true, rpcPort: true, rpcToken: true, rpcTest: true }) : (config.downloadMethod = "右键保存", API.changeSettingMode({ referer: true, useragent: true, filepath: true, IDMLater: true, IDMToast: true, rpcServer: true, rpcPort: true, rpcToken: true, rpcTest: true })); API.displaySetting("downloadMethod"); }); break; case "aria2": API.alertMessage(\`aria2是一款著名的命令行下载工具,使用本方式将在您点击下载面板中的链接时将命令行复制到您的剪切板中,您可以粘贴到cmd等终端中回车进行下载。您必须先下载aria2工具并添加系统环境变量或者在终端在打开aria2二进制文件所在目录!\`).then(d => { d ? API.changeSettingMode({ referer: false, useragent: false, filepath: false, IDMLater: true, IDMToast: true, rpcServer: true, rpcPort: true, rpcToken: true, rpcTest: true }) : (config.downloadMethod = "右键保存", API.changeSettingMode({ referer: true, useragent: true, filepath: true, IDMLate: true, IDMToast: true, rpcServer: true, rpcPort: true, rpcToken: true, rpcTest: true })); API.displaySetting("downloadMethod"); }); break; case "aira2 RPC": API.alertMessage(\`aria2支持RPC方式接收下载数据,您需要在aria2配置开启RPC功能并保持后台运行,并在本脚本设置中配置好aria2主机及端口。
          点击确定将刷新设置面板并呈现相关设置。\`).then(d => { d ? API.changeSettingMode({ referer: false, useragent: false, filepath: false, IDMLater: true, IDMToast: true, rpcServer: false, rpcPort: false, rpcToken: false, rpcTest: false }) : (config.downloadMethod = "右键保存", API.changeSettingMode({ referer: true, useragent: true, filepath: true, IDMLater: true, IDMToast: true, rpcServer: true, rpcPort: true, rpcToken: true, rpcTest: true })); API.displaySetting("downloadMethod"); }); break; default: API.changeSettingMode({ referer: true, useragent: true, filepath: true, IDMLater: true, IDMToast: true, rpcServer: true, rpcPort: true, rpcToken: true, rpcTest: true }); API.displaySetting("downloadMethod"); } } }); API.registerSetting({ type: "input", sort: "download", key: "useragent", label: "User-Agent", value: "Bilibili Freedoooooom/MarkII", input: { type: "text" }, float: \`用户代理,此值不可为空,默认使用B站客户端专属UA。\`, hidden: config.downloadMethod == "右键保存" }); API.registerSetting({ type: "input", sort: "download", key: "referer", label: "referer", value: location.origin, input: { type: "text" }, float: \`一般为B站主域名(http://www.bilibili.com)。
          APP/TV等视频源必须为空!\`, hidden: config.downloadMethod == "右键保存" }); API.registerSetting({ type: "input", sort: "download", key: "filepath", label: "保存目录", value: "", input: { type: "text", placeholder: "如:D\\\\下载" }, float: 'windows端请注意反斜杠!', hidden: config.downloadMethod == "右键保存" }); API.registerSetting({ key: "IDMLater", sort: "download", label: "稍后下载", sub: "添加到IDM列表而不立即下载", type: "switch", value: false, float: "把下载链接添加到下载列表但是不立即开始下载,需要下载时再手动到IDM里开始。B站下载链接一般都有时效,太久不下载的话链接可能失效!", hidden: config.downloadMethod != "ef2" }); API.registerSetting({ key: "IDMToast", sort: "download", label: "静默下载", sub: "不用IDM确认框", type: "switch", value: false, float: "禁用IDM下载前的询问弹窗,其中可以选择修改文件名及保存目录等信息。", hidden: config.downloadMethod != "ef2" }); API.registerSetting({ key: "rpcServer", sort: "download", label: "RPC主机", type: "input", input: { type: "url", placeholder: "如:http(s)://localhost" }, value: "http://localhost", hidden: config.downloadMethod != "aira2 RPC" }); API.registerSetting({ key: "rpcPort", sort: "download", label: "RPC端口", type: "input", input: { type: "number", placeholder: "如:6800" }, value: 6800, hidden: config.downloadMethod != "aira2 RPC" }); API.registerSetting({ key: "rpcToken", sort: "download", label: "RPC令牌(可选)", type: "input", input: { type: "password" }, value: "", hidden: config.downloadMethod != "aira2 RPC" }); API.registerSetting({ key: "rpcTest", sort: "download", label: "RPC调试", type: "action", title: "测试", hidden: config.downloadMethod != "aira2 RPC", action: () => { API.aria2.getVersion() .then(d => toast.success(\`RPC设置正常!aria2版本:\${d.version}\`)) .catch(e => toast.error("RPC链接异常!请检查各项设置以及RPC主机的状况!", e)); } }); API.registerSetting({ key: "dlDmCC", sort: "download", label: "其他下载", sub: "弹幕、CC字幕等", type: "sort", list: [ { key: "ifDlDmCC", sort: "download", label: "弹幕、CC字幕、封面", type: "switch", value: false }, { key: "dlDmType", sort: "download", label: "弹幕格式", type: "row", value: "xml", list: ["xml", "json"], float: \`xml是经典的B站弹幕格式,json是旧版播放器直接支持的格式,本脚本载入本地弹幕功能同时支持这两种。
          如果只是给本脚本专用那就选json,xml对“非法字符”支持不友好,部分高级/代码/BAS弹幕可能出错。\` } ] }); // 旧版播放器专属设置 API.registerSetting({ key: "onlineDanmaku", sort: "danmaku", label: "在线弹幕", type: "input", float: '为当前旧版播放器载入其他站内视频弹幕,可以输入URL或者aid等参数。
          ※ 可配合选择是否合并已有弹幕。', input: { type: "url", placeholder: "URL" }, title: "载入", hidden: true, action: (url) => { if (!window.player?.setDanmaku) return toast.warning("内部组件丢失,已停止!"); API.danmaku.onlineDanmaku(url); } }); API.registerSetting({ key: "allDanmaku", sort: "danmaku", label: "全弹幕装填", type: "sort", float: '获取所有能获取的历史弹幕。
          ※ 该操作耗时较长且可能造成B站临时封接口,请慎用!', hidden: true, list: [{ key: "allDanmakuDelay", sort: "danmaku", label: "冷却时间:/s", type: "input", value: 3, input: { type: "number", min: 1, max: 60, step: 0.5 }, float: '接口冷却时间,时间长可以降低被临时封端口的几率。' }, { key: "allDanmakuAction", sort: "danmaku", label: "开始获取", type: "action", title: "开始", action: function () { if (!window.player?.setDanmaku) return toast.warning("内部组件丢失,已停止!"); new API.allDanmaku(); }, disabled: 0 }] }); API.registerSetting({ key: "localMedia", sort: "player", label: "载入本地文件", sub: "视频/弹幕", type: "file", accept: [".mp4", ".xml", ".json"], float: '使用旧版播放器播放本地视频或者弹幕文件。
          ※ 视频只能为mp4格式,且编码格式被浏览器所兼容。
          ※ 若载入弹幕文件,参见弹幕设置是否合并弹幕。', title: "文件", hidden: true, action: (files) => { (!window.player?.setDanmaku) && toast.warning("内部组件丢失,无法载入弹幕文件!"); new API.localMedia(files); } }); API.path && API.path.name && API.runWhile(() => API.path.name && window.player, () => { API.changeSettingMode({ onlineDanmaku: false, allDanmaku: false, localMedia: false }); }); API.registerSetting({ key: "commentLinkDetail", sort: "style", label: "还原评论中的超链接", sub: "av、ss或ep", type: "switch", value: false }); API.registerSetting({ key: "configManage", sort: "common", svg: '', label: "设置数据", sub: "备份/恢复", type: "action", title: "管理", action: () => API.importModule("manage.js") }); API.registerSetting({ key: "oldReplySort", sort: "style", label: "评论区优先展示按时间排序", sub: "疏于维护的特别需求", type: "switch", value: false, float: "B站曾经默认优先以时间顺序展示评论,并在最前列展示几条热评。本脚本尝试恢复过本功能,但如今已疏于维护。" }); API.registerSetting({ key: "anime", sort: "rewrite", label: "番剧分区", type: "switch", value: false, float: '重构以恢复旧版番剧分区。' }); API.registerSetting({ type: "row", sort: "player", key: "codecType", label: "优先载入的视频编码类型", sub: "AVC、HEVC或AV1", value: "AVC", list: ["AVC", "HEVC", "AV1"], float: '播放器会尽量优先加载所选择的编码,可根据设备解码能力与实际需要调整这个设置项。AVC兼容性最佳,AV1次之,HEVC则只有Safari支持,edge可通过一些操作进行支持。有关视频编码格式可查阅其他专业文档。', action: type => { let mime = { "HEVC": 'video/mp4;codecs="hev1.1.6.L120.90"', "AV1": 'video/mp4;codecs="av01.0.01M.08.0.110.01.01.01.0"', "AVC": 'video/mp4;codecs="avc1.640028"' }; if (!MediaSource.isTypeSupported(mime[type])) { toast.warning(\`播放器不支持\${type}编码格式\`, "将继续使用AVC编码"); config.codecType = "AVC"; API.displaySetting("codecType"); } } }); } //# sourceURL=API://@Bilibili-Old/include/setting.js`; /*!***********************!*/ /**/modules["switchVideo.js"] = /*** ./dist/include/switchVideo.js ***/ `{ const switchlist = []; /** * 注册切P回调 * @param callback 切P时的回调函数 */ function switchVideo(callback) { try { if (typeof callback === "function") switchlist.push(callback); } catch (e) { toast.error("switchVideo.js", e); } } API.switchVideo = (callback) => switchVideo(callback); API.observerAddedNodes((node) => { if (/bilibili-player-area video-state-pause/.test(node.className)) { switchlist.forEach(async (d) => { try { d(); } catch (e) { debug.error(d); debug.error(e); } }); } }); } //# sourceURL=API://@Bilibili-Old/include/switchVideo.js`; /*!***********************!*/ /**/modules["ui.js"] = /*** ./dist/include/ui.js ***/ `{ API.registerSetting({ key: "settingEntryType", svg: '', sort: "common", type: "switch", label: "经典设置入口", sub: "贴边隐藏", value: false }); // @ts-expect-error 专属变量 const menu = MENU, setting = SETTING; class Ui { /** * UI顶层 */ static box; /** * 工具栏按钮栏 */ static tool; /** * 分类菜单栏 */ static menu; /** * 设置实际界面 */ static item; /** * 输入框历史缓存 */ static history; /** * 设置项表 */ static list = {}; constructor() { const history = GM.getValue("history", {}); Ui.history = new Proxy(history, { set: (_target, p, value) => { history[p] = value; GM.setValue("history", history); return true; }, get: (_target, p) => history[p] }); this.stage(); } /** * 设置入口 */ async stage() { if (document.readyState !== 'complete') { await new Promise(r => window.addEventListener('load', r)); } if (config.settingEntryType) return this.classical(); const div = API.addElement("div").attachShadow({ mode: "closed" }); const stage = API.addElement("div", { class: "stage" }, div, \`\`); API.addCss(API.getModule("ui-stage.css"), "", div); stage.onclick = () => this.display(); stage.onmouseover = () => stage.style.opacity = "0.8"; setTimeout(() => { stage.style.opacity = "0"; stage.onmouseout = () => stage.style.opacity = "0"; }, 2e3); } /** * 经典设置入口 */ async classical() { const div = API.addElement("div").attachShadow({ mode: "closed" }); const classical = API.addElement("div", { class: "classical" }, div, \`设置\`); API.addCss(API.getModule("ui-stage.css"), "", div); classical.onclick = () => this.display(); } /** * 呈现设置界面 * @param key 设置项的key,直接滚动到对应设置 */ display(key) { document.querySelector("#ui-border-box")?.remove(); Ui.borderBox(); setting.reduce((s, d) => { d.sort && !s.includes(d.sort) && (Ui.menuitem(d.sort), s.push(d.sort)); Ui.index(d); return s; }, []); document.body.appendChild(Ui.box); Ui.tool.childNodes.forEach((d, i) => { (i < (Ui.tool.childNodes.length - 1)) && (d.style.opacity = "0"); }); Ui.tool.onmouseover = () => { Ui.tool.childNodes.forEach((d, i) => { (i < (Ui.tool.childNodes.length - 1)) && (d.style.opacity = "1"); }); }; Ui.tool.onmouseout = () => { Ui.tool.childNodes.forEach((d, i) => { (i < (Ui.tool.childNodes.length - 1)) && (d.style.opacity = "0"); }); }; key && Reflect.has(Ui.list, key) && Ui.list[key].scrollIntoView({ behavior: 'smooth', block: 'center' }); } static borderBox() { this.box = document.createElement("div"); this.box.setAttribute("id", "ui-border-box"); const root = this.box.attachShadow({ mode: "closed" }); const div = API.addElement("div", { class: "box" }, root, \`
          \`); API.addCss(API.getModule("ui.css"), "", root); this.tool = div.children[0]; this.menu = div.children[1].children[0].children[0]; this.item = div.children[1].children[0].children[1]; this.toolIcon({ type: "icon", svg: '', title: "关闭", action: (node) => node.remove() }); } /** * 添加工具栏按钮 * @param obj 按钮配置数据 */ static toolIcon(obj) { const div = this.icon(obj.svg); div.setAttribute("title", obj.title); this.tool.insertBefore(div, this.tool.firstChild); div.onclick = () => obj.action(this.box); return div; } /** * 创建图标节点 * @param svg 图标 svg 字符串 * @returns 图标节点 */ static icon(svg) { const div = document.createElement("div"); const root = div.attachShadow({ mode: "closed" }); API.addElement("div", { class: "icon" }, root, svg); API.addCss(API.getModule("icon.css"), "", root); return div; } /** * 添加菜单栏 * @param key 菜单主键 */ static menuitem(key) { let obj = menu[key]; const div = API.addElement("div", {}, this.menu); const root = div.attachShadow({ mode: "closed" }); const real = API.addElement("div", { class: "menuitem" }, root); API.addCss(API.getModule("ui-menu.css"), "", root); obj.svg && real.appendChild(this.icon(obj.svg)); real.appendChild(document.createTextNode(obj.name)); div.onclick = () => { let selected = this.menu.querySelector(".selected"); let itembox = this.item.querySelector(\`.\${obj.key}\`); selected && selected.removeAttribute("class"); itembox && itembox.scrollIntoView({ behavior: 'smooth', block: 'center' }); div.setAttribute("class", "selected"); }; } /** * 添加菜单组合项 * @param key 菜单主键 * @returns 组合框节点,用以添加设计设置项 */ static itemContain(key) { let obj = menu[key]; let div = this.item.querySelector(\`.\${obj.key}\`); if (!div) { div = API.addElement("div", { class: obj.key }, this.item); const root = div.attachShadow({ mode: "open" }); API.addElement("div", { class: "contain" }, root, \`

          \${obj.name}

          \`); API.addCss(API.getModule("ui-contain.css"), "", root); } return div.shadowRoot.querySelector(".card"); } /** * 创建浮动信息,鼠标移动该节点上时显示 * @param node 浮动信息所属节点 * @param data 浮动信息内容 */ static float(node, data) { const div = document.createElement("div"); const root = div.attachShadow({ mode: "closed" }); const real = API.addElement("div", { class: "float" }, root, \`
          \${data}
          \`); API.addCss(API.getModule("ui-float.css"), "", root); node.onmouseover = (ev) => { document.body.appendChild(div); let rect = real.getBoundingClientRect(); real.style.left = \`\${node.getBoundingClientRect().x + ev.offsetX}px\`; real.style.top = \`\${node.getBoundingClientRect().y + ev.offsetY - rect.height}px\`; real.style.width = \`\${Math.sqrt(rect.width * rect.height) * 4 / 3}px\`; }; node.onmouseout = () => div.remove(); this.box.addEventListener("DOMNodeRemovedFromDocument", async () => div?.remove()); } /** * 设置分类 * @param obj 设置内容 * @param node 父节点 * @returns 设置节点 */ static index(obj, node) { let result; if (!obj.hidden) switch (obj.type) { case "action": result = this.action(obj, node); break; case "file": result = this.file(obj, node); break; case "input": result = this.input(obj, node); break; case "mutlti": result = this.multi(obj, node); break; case "picture": result = this.picture(obj, node); break; case "row": result = this.row(obj, node); break; case "sort": result = this.sort(obj, node); break; case "switch": result = this.switch(obj, node); break; case "icon": result = this.toolIcon(obj); break; case "custom": result = this.custom(obj); } return result; } /** * 添加纯图片设置 * @param obj 设置内容 * @param node 父节点 * @returns 设置节点 */ static picture(obj, node) { node = node || this.itemContain(obj.sort); const div = document.createElement("div"); const root = div.attachShadow({ mode: "closed" }); const real = API.addElement("div", { class: "contain" }, root, \`\`); API.addCss(API.getModule("ui-picture.css"), "", root); node && node.appendChild(div); obj.callback && new Promise(r => obj.callback.call(real)); return div; } /** * 添加开关设置 * @param obj 设置内容 * @param node 父节点 * @returns 设置节点 */ static switch(obj, node) { node = node || this.itemContain(obj.sort); const div = document.createElement("div"); const root = div.attachShadow({ mode: "closed" }); const real = API.addElement("div", { class: "contain" }, root); API.addCss(API.getCss("ui-item.css"), "", root); Reflect.set(this.list, obj.key, real); obj.svg && real.appendChild(this.icon(obj.svg)); const label = API.addElement("div", { class: "label" }, real, obj.label); real.appendChild(API.element.switch(function (v) { config[obj.key] = v; obj.action && obj.action.call(this, config[obj.key]); }, config[obj.key])); obj.sub && (label.innerHTML = \`\${obj.label}
          \${obj.sub}
          \`); obj.float && this.float(real, obj.float); node && node.appendChild(div); obj.callback && new Promise(r => obj.callback.call(real)); return div; } /** * 添加下拉设置 * @param obj 设置内容 * @param node 父节点 * @returns 设置节点 */ static row(obj, node) { node = node || this.itemContain(obj.sort); let div = document.createElement("div"); const root = div.attachShadow({ mode: "closed" }); const real = API.addElement("div", { class: "contain" }, root); Reflect.set(this.list, obj.key, real); API.addCss(API.getCss("ui-item.css"), "", root); obj.svg && real.appendChild(this.icon(obj.svg)); const label = API.addElement("div", { class: "label" }, real, obj.label); real.appendChild(API.element.select(obj.list, function (v) { config[obj.key] = v; config[obj.key] = v; obj.action && obj.action.call(this, v); }, config[obj.key])); obj.sub && API.addElement("div", { class: "sub" }, label, obj.sub); obj.float && this.float(real, obj.float); node && node.appendChild(div); obj.callback && new Promise(r => obj.callback.call(real)); return div; } /** * 添加归档设置 * @param obj 设置内容 * @param node 父节点 * @returns 设置节点 */ static sort(obj, node) { node = node || this.itemContain(obj.sort); let div = document.createElement("div"); let sec = document.createElement("div"); let flag = false; let item; const root = div.attachShadow({ mode: "closed" }); const real = API.addElement("div", { class: "contain" }, root); Reflect.set(this.list, obj.key, real); API.addCss(API.getModule("ui-sort-head.css"), "", root); const secroot = sec.attachShadow({ mode: "closed" }); const secreal = API.addElement("div", { class: "contain" }, secroot); API.addCss(API.getModule("ui-sort-body.css"), "", secroot); obj.svg && real.appendChild(this.icon(obj.svg)); const label = API.addElement("div", { class: "label" }, real, obj.label); const value = API.addElement("div", { class: "anchor" }, real); value.appendChild(this.icon(\`\`)); obj.sub && (label.innerHTML = \`\${obj.label}
          \${obj.sub}
          \`); obj.float && this.float(real, obj.float); node && node.appendChild(div) && node.appendChild(sec); obj.callback && new Promise(r => obj.callback.call(real)); item = obj.list.reduce((s, d) => { let temp = this.index(d, secreal); temp.style.display = "none"; s.push(temp); return s; }, []); value.onclick = () => { flag = !flag; flag ? value.setAttribute("checked", "checked") : value.removeAttribute("checked"); flag ? item.forEach(d => d.style.display = "block") : item.forEach(d => d.style.display = "none"); }; return div; } /** * 添加按钮菜单 * @param obj 设置内容 * @param node 父节点 * @returns 设置节点 */ static action(obj, node) { node = node || this.itemContain(obj.sort); let div = document.createElement("div"); let disabled = obj.hasOwnProperty("disabled") ? obj.disabled : 3; const root = div.attachShadow({ mode: "closed" }); const real = API.addElement("div", { class: "contain" }, root); Reflect.set(this.list, obj.key, real); API.addCss(API.getModule("ui-item.css"), "", root); obj.svg && real.appendChild(this.icon(obj.svg)); const label = API.addElement("div", { class: "label" }, real, obj.label); real.appendChild(API.element.button(function () { obj.action.call(this); }, obj.title, disabled)); obj.sub && (label.innerHTML = \`\${obj.label}
          \${obj.sub}
          \`); obj.float && this.float(real, obj.float); node && node.appendChild(div); obj.callback && new Promise(r => obj.callback.call(real)); return div; } /** * 添加输入框设置 * @param obj 设置内容 * @param node 父节点 * @returns 设置节点 */ static input(obj, node) { node = node || this.itemContain(obj.sort); let div = document.createElement("div"); let history = []; let disabled = obj.hasOwnProperty("disabled") ? obj.disabled : 3; const root = div.attachShadow({ mode: "closed" }); const real = API.addElement("div", { class: "contain" }, root); Reflect.set(this.list, obj.key, real); API.addCss(API.getModule("ui-input.css"), "", root); obj.svg && real.appendChild(this.icon(obj.svg)); API.addElement("div", { style: "padding-inline-start: 12px;flex: 1;flex-basis: 0.000000001px;padding-block-end: 12px;padding-block-start: 12px;" }, real, obj.label); const value = API.addElement("div", { class: "textbox" }, real); obj.key ? (API.addElement("input", { list: \`list-\${obj.key}\` }, value), API.addElement("datalist", { id: \`list-\${obj.key}\` }, value), value.appendChild(this.icon(\`\`))) : API.addElement("input", {}, value); obj.title && API.addElement("div", { class: "button" }, value, obj.title); (history = this.history[obj.key] || [], history.reduce((s, d) => { API.addElement("option", { value: d || "" }, s); return s; }, value.children[1]), value.children[2].setAttribute("style", "display: none;cursor: pointer;pointer-events: auto;position: absolute;right: 100%;background-color: white;")); obj.float && this.float(real, obj.float); node && node.appendChild(div); obj.callback && new Promise(r => obj.callback.call(real)); let input = value.children[0]; let clear = value.children[2]; obj.hasOwnProperty("value") && (input.value = config[obj.key]); Object.entries(obj.input).forEach(d => { input.setAttribute(d[0], d[1]); }); value.onmouseover = () => history.length > 0 && (clear && (clear.style.display = "block")); value.onmouseout = () => { clear && (clear.style.display = "none"); }; clear && (clear.onclick = () => { history = this.history[obj.key] = []; real.querySelectorAll("option").forEach(d => d.remove()); clear.style.display = "none"; }); obj.title ? (real.querySelector(".button").onclick = () => { if (!input.value || (config[obj.key] == input.value)) return; if (obj.pattern && !obj.pattern.test(input.value)) return toast.warning("非法输入!", \`正则限制:\${obj.pattern.toString()}\`); real.querySelector(".button").setAttribute("disabled", "disabled"); disabled && setTimeout(() => real.querySelector(".button").removeAttribute("disabled"), disabled * 1000); obj.hasOwnProperty("value") && (config[obj.key] = input.value, config[obj.key] = input.value); !history.includes(input.value) && history.push(input.value) && (this.history[obj.key] = history); obj.action && obj.action.call(real, input.value); }) : (input.onchange = () => { if (obj.pattern && !obj.pattern.test(input.value)) return toast.warning("非法输入!", \`正则限制:\${obj.pattern.toString()}\`); obj.hasOwnProperty("value") && (config[obj.key] = input.value, config[obj.key] = input.value); !history.includes(input.value) && history.push(input.value) && (this.history[obj.key] = history); obj.action && obj.action.call(real, input.value); }); return div; } /** * 添加文件选择设置 * @param obj 设置内容 * @param node 父节点 * @returns 设置节点 */ static file(obj, node) { node = node || this.itemContain(obj.sort); let div = document.createElement("div"); const root = div.attachShadow({ mode: "closed" }); const real = API.addElement("div", { class: "contain" }, root); Reflect.set(this.list, obj.key, real); API.addCss(API.getModule("ui-file.css"), "", root); obj.svg && real.appendChild(this.icon(obj.svg)); const label = API.addElement("div", { class: "label" }, real, obj.label); const value = API.addElement("div", { class: "button" }, real, obj.title); const input = API.addElement("input", { type: "file", style: "width: 0;" }, real); obj.sub && (label.innerHTML = \`\${obj.label}
          \${obj.sub}
          \`); obj.accept && (input.accept = obj.accept.join(",")); obj.multiple && (input.multiple = true); obj.float && this.float(real, obj.float); node && node.appendChild(div); obj.callback && new Promise(r => obj.callback.call(real)); value.onclick = () => input.click(); input.onclick = () => input.value = ""; input.onchange = () => input.files && obj.action.call(real, input.files); return div; } /** * 添加复选设置 * @param obj 设置内容 * @param node 父节点 * @returns 设置节点 */ static multi(obj, node) { node = node || this.itemContain(obj.sort); let div = document.createElement("div"); const root = div.attachShadow({ mode: "closed" }); const real = API.addElement("div", { class: "contain" }, root); Reflect.set(this.list, obj.key, real); API.addCss(API.getModule("ui-item.css"), "", root); obj.svg && real.appendChild(this.icon(obj.svg)); const label = API.addElement("div", { class: "label" }, real, obj.label); real.appendChild(API.element.checkbox(obj.list, function (v) { config[obj.key] = v; obj.action && obj.action.call(this, v); }, config[obj.key])); obj.sub && (label.innerHTML = \`\${obj.label}
          \${obj.sub}
          \`); obj.float && this.float(real, obj.float); node && node.appendChild(div); obj.callback && new Promise(r => obj.callback.call(real)); return div; } /** * 添加自定义设置 * @param obj 设置内容 * @param node 父节点 * @returns 设置节点 */ static custom(obj, node) { node = node || this.itemContain(obj.sort); let div = document.createElement("div"); const root = div.attachShadow({ mode: "open" }); const real = API.addElement("div", { class: "contain" }, root); const table = {}; Reflect.set(this.list, obj.key, real); API.addCss(API.getModule("ui-item.css"), "", root); obj.svg && real.appendChild(table.svg = this.icon(obj.svg)); table.label = API.addElement("div", { class: "label" }, real, obj.label); table.value = API.addElement("div", {}, real, obj.custom); obj.sub && (table.label.innerHTML = \`\${obj.label}
          \${obj.sub}
          \`); obj.float && this.float(real, obj.float); node && node.appendChild(div); obj.callback && new Promise(r => obj.callback.call(real)); obj.flesh && obj.flesh.call(real, new Proxy(obj, { set: (t, p, v) => { Reflect.set(obj, p, v); switch (p) { case "svg": table.temp = this.icon(v); table.svg.replaceWith(table.temp); table.svg = table.temp; break; case "label": table.label = API.addElement("div", { class: "label" }, real, v, false, table.label); break; case "custom": table.value = API.addElement("div", {}, real, v, false, table.value); break; case "sub": table.label.innerHTML = \`\${obj.label}
          \${v}
          \`; break; } return true; } })); return div; } } API.importModule("setting.js"); // 空闲时间检查一下默认设置 const ui = new Ui(); API.displaySetting = (key) => ui.display(key); API.danmaku; } //# sourceURL=API://@Bilibili-Old/include/ui.js`; /*!***********************!*/ /**/modules["url.js"] = /*** ./dist/include/url.js ***/ `class _Url { access_key = GM.getValue("access_key", undefined); /** * url的默认参数,即UrlDetail未列出或可选的部分 */ jsonUrlDefault = { "api.bilibili.com/pgc/player/web/playurl": { qn: 127, otype: 'json', fourk: 1 }, "api.bilibili.com/x/player/playurl": { qn: 127, otype: 'json', fourk: 1 }, "interface.bilibili.com/v2/playurl": { appkey: 9, otype: 'json', quality: 127, type: '' }, "bangumi.bilibili.com/player/web_api/v2/playurl": { appkey: 9, module: "bangumi", otype: 'json', quality: 127, type: '' }, "api.bilibili.com/pgc/player/api/playurlproj": { access_key: this.access_key, appkey: 1, build: "2040100", device: "android", expire: "0", mid: "0", mobi_app: "android_i", module: "bangumi", otype: "json", platform: "android_i", qn: 127, ts: new Date().getTime() }, "app.bilibili.com/v2/playurlproj": { access_key: this.access_key, appkey: 1, build: "2040100", device: "android", expire: "0", mid: "0", mobi_app: "android_i", otype: "json", platform: "android_i", qn: 127, ts: new Date().getTime() }, "api.bilibili.com/pgc/player/api/playurltv": { appkey: 6, qn: 127, fourk: 1, otype: 'json', platform: "android", mobi_app: "android_tv_yst", build: 102801 }, "api.bilibili.com/x/tv/ugc/playurl": { appkey: 6, qn: 127, fourk: 1, otype: 'json', platform: "android", mobi_app: "android_tv_yst", build: 102801 }, "app.bilibili.com/x/intl/playurl": { access_key: this.access_key, mobi_app: "android_i", fnver: 0, fnval: API.fnval, qn: 127, platform: "android", fourk: 1, build: 2100110, appkey: 0, otype: 'json', ts: new Date().getTime() }, "apiintl.biliapi.net/intl/gateway/ogv/player/api/playurl": { access_key: this.access_key, mobi_app: "android_i", fnver: 0, fnval: API.fnval, qn: 127, platform: "android", fourk: 1, build: 2100110, appkey: 0, otype: 'json', ts: new Date().getTime() }, "api.bilibili.com/view": { type: "json", appkey: "8e9fc618fbd41e28" } }; /** * 请求封装好的json请求 * @param url 请求的url * @param detail 请求所需配置数据 * @param GM 是否使用跨域请求 * @returns Promise封装的返回值 */ getJson(url, detail, GM = false) { let obj = { ...(this.jsonUrlDefault[url] || {}), ...detail }; (Number(Reflect.get(obj, "appkey")) >= 0) && (obj = this.sign(obj)); return GM ? xhr.GM({ url: Format.objUrl(\`//\${url}\`, obj), responseType: "json" }) : xhr({ url: Format.objUrl(\`//\${url}\`, obj), responseType: "json", credentials: true }); } sign(obj) { return Format.urlObj(\`?\${API.urlsign("", obj, obj.appkey)}\`); } } API.url = _Url; //# sourceURL=API://@Bilibili-Old/include/url.js`; /*!***********************!*/ /**/modules["urlInputCheck.js"] = /*** ./dist/include/urlInputCheck.js ***/ `{ /** * 将数据缓存起来,以免重复查询 */ const catchs = { aid: {}, ssid: {}, epid: {} }; API.urlInputCheck = async function (input) { let aid, cid, ssid, epid, p, pgc = false; toast("正在解析链接:" + input); if (input && !input.includes("?")) input = "?" + input; // 重整化输入便于提取参数 let obj = Format.urlObj(input); // 获取参数对象 aid = input.match(/[aA][vV][0-9]+/) ? input.match(/[aA][vV][0-9]+/)[0].match(/\\d+/)[0] : undefined; aid = aid || obj.aid || undefined; aid = aid || (/[bB][vV]1[fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF]{9}/.test(input) ? API.abv(input.match(/[bB][vV]1[fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF]{9}/)[0]) : undefined); aid = aid || (obj.bvid ? API.abv(obj.bvid) : undefined); p = obj.p || 1; try { if (aid) { if (aid == API.aid) cid = API.cid; // 有缓存数据的情况 cid = catchs.aid[aid] && catchs.aid[aid][p - 1].cid; // 直接获取到cid的情况 cid = cid || obj.cid || undefined; if (!cid) { try { // 尝试访问B站服务器获取信息 catchs.aid[aid] = API.jsonCheck(await xhr({ url: Format.objUrl("https://api.bilibili.com/x/player/pagelist", { "aid": aid }) })).data; cid = catchs.aid[aid][p - 1].cid; toast("正在请求av视频数据", "分P名称:" + catchs.aid[aid][p - 1].part); } catch (e) { e = Array.isArray(e) ? e : [e]; debug.error("获取视频信息出错:aid:" + aid, "HOST:https://api.bilibili.com/x/player/pagelist", ...e); try { // 尝试访问BiliPlus获取信息 let data = API.jsonCheck(await xhr({ url: Format.objUrl("https://www.biliplus.com/api/view", { "id": aid }) })); catchs.aid[aid] = data.list || (data.v2_app_api && data.v2_app_api.pages); cid = catchs.aid[aid][p - 1].cid; toast("正在请求av视频数据", "分P名称:" + catchs.aid[aid][p - 1].part); } catch (e) { e = Array.isArray(e) ? e : [e]; debug.error("获取视频信息出错:aid:" + aid, "HOST:https://www.biliplus.com/api/view", ...e); } } } } else { // 输入的是番剧ss/ep链接的情况,尝试获取aid、cid ssid = input.match(/[sS][sS][0-9]+/) ? input.match(/[sS][sS][0-9]+/)[0].match(/\\d+/)[0] : undefined; ssid = ssid || obj.season_id || undefined; epid = input.match(/[eE][pP][0-9]+/) ? input.match(/[eE][pP][0-9]+/)[0].match(/\\d+/)[0] : undefined; epid = epid || obj.ep_id || undefined; try { // 尝试访问bangumi接口 let data; if (epid) data = JSON.stringify(catchs.epid[epid]) || await xhr({ url: Format.objUrl("https://bangumi.bilibili.com/view/web_api/season", { ep_id: epid }) }); else if (ssid) data = JSON.stringify(catchs.ssid[ssid]) || await xhr({ url: Format.objUrl("https://bangumi.bilibili.com/view/web_api/season", { season_id: ssid }) }); if (data) { data = new API.initialStateOfBangumi(data, epid).season(); ssid && (catchs.ssid[ssid] = data); epid && (catchs.epid[epid] = data); aid = data.epInfo.aid; cid = data.epInfo.cid; pgc = true; toast("正在请求Bangumi数据", "系列名称:" + data.mediaInfo.title, "分p名称:" + data.epInfo.index_title); } } catch (e) { e = Array.isArray(e) ? e : [e]; let data; if (ssid) debug.error("获取视频信息出错:ssid:" + ssid, "HOST:https://bangumi.bilibili.com/view/web_api/season", ...e); else if (epid) debug.error("获取视频信息出错:epid:" + epid, "HOST:https://bangumi.bilibili.com/view/web_api/season", ...e); try { if (epid) { data = await xhr({ url: Format.objUrl(\`\${config.limitServer}/intl/gateway/v2/ogv/view/app/season\`, { ep_id: epid }) }); } else if (ssid) { data = await xhr({ url: Format.objUrl(\`\${config.limitServer}/intl/gateway/v2/ogv/view/app/season\`, { season_id: ssid }) }); } data = new API.initialStateOfBangumi(data, epid).global(); aid = data.epInfo.aid; cid = data.epInfo.cid; pgc = true; toast("正在请求Bangumi数据", "系列名称:" + data.mediaInfo.title, "分p名称:" + data.epInfo.index_title); } catch (e) { } } } } catch (e) { toast.error("urlInputCheck.js", e); } return { aid, cid, ssid, epid, p, pgc }; }; } //# sourceURL=API://@Bilibili-Old/include/urlInputCheck.js`; /*!***********************!*/ /**/modules["abv.js"] = /*** ./dist/lib/abv.js ***/ `class Abv { base58Table = 'fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF'; digitMap = [11, 10, 3, 8, 4, 6]; xor = 177451812; add = 8728348608; bvidTemplate = ['B', 'V', 1, '', '', 4, '', 1, '', 7, '', '']; table = {}; constructor() { for (let i = 0; i < 58; i++) this.table[this.base58Table[i]] = i; } /** * av/BV互转 * @param input av或BV,可带av/BV前缀 * @returns 转化结果 */ check(input) { if (/^[aA][vV][0-9]+\$/.test(String(input)) || /^\\d+\$/.test(String(input))) return this.avToBv(Number(/[0-9]+/.exec(String(input))[0])); if (/^1[fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF]{9}\$/.test(String(input))) return this.bvToAv("BV" + input); if (/^[bB][vV]1[fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF]{9}\$/.test(String(input))) return this.bvToAv(String(input)); throw input; } bvToAv(BV) { let r = 0; for (let i = 0; i < 6; i++) r += this.table[BV[this.digitMap[i]]] * 58 ** i; return (r - this.add) ^ this.xor; } avToBv(av) { let bv = Array.from(this.bvidTemplate); av = (av ^ this.xor) + this.add; for (let i = 0; i < 6; i++) bv[this.digitMap[i]] = this.base58Table[parseInt(String(av / 58 ** i)) % 58]; return bv.join(""); } } API.abv = (input) => new Abv().check(input); //# sourceURL=API://@Bilibili-Old/lib/abv.js`; /*!***********************!*/ /**/modules["Base64.js"] = /*** ./dist/lib/Base64.js ***/ `class Base64 { /** * Base64编码 * @param str 原始字符串 * @returns 编码结果 */ static encode(str) { return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { return String.fromCharCode(('0x' + p1)); })); } /** * Base64解码 * @param str 原始字符串 * @returns 解码结果 */ static decode(str) { return decodeURIComponent(atob(str).split('').map(function (c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); } } API.base64 = Base64; //# sourceURL=API://@Bilibili-Old/lib/Base64.js`; /*!***********************!*/ /**/modules["crc32.js"] = /*** ./dist/lib/crc32.js ***/ `class Midcrc { CRCPOLYNOMIAL = 0xEDB88320; crctable = new Array(256); index = new Array(4); constructor() { this.create_table(); } /** * @param input 输入crc32散列值 * @returns 逆向出的mid值 */ run(input) { let ht = parseInt('0x' + input) ^ 0xffffffff, snum, i, lastindex, deepCheckData; for (i = 3; i >= 0; i--) { this.index[3 - i] = this.getcrcindex(ht >>> (i * 8)); snum = this.crctable[this.index[3 - i]]; ht ^= snum >>> ((3 - i) * 8); } for (i = 0; i < 10000000; i++) { lastindex = this.crc32lastindex(i); if (lastindex == this.index[3]) { deepCheckData = this.deepCheck(i, this.index); if (deepCheckData[0]) break; } } if (i == 10000000) return -1; return Number(i + '' + deepCheckData[1]); } create_table() { let crcreg, i, j; for (i = 0; i < 256; ++i) { crcreg = i; for (j = 0; j < 8; ++j) { if ((crcreg & 1) !== 0) { crcreg = this.CRCPOLYNOMIAL ^ (crcreg >>> 1); } else { crcreg >>>= 1; } } this.crctable[i] = crcreg; } } crc32(input) { if (typeof (input) != 'string') input = input.toString(); let crcstart = 0xFFFFFFFF, len = input.length, index; for (let i = 0; i < len; ++i) { index = (crcstart ^ input.charCodeAt(i)) & 0xff; crcstart = (crcstart >>> 8) ^ this.crctable[index]; } return crcstart; } crc32lastindex(input) { if (typeof (input) != 'string') input = input.toString(); let crcstart = 0xFFFFFFFF, len = input.length, index; for (let i = 0; i < len; ++i) { index = (crcstart ^ input.charCodeAt(i)) & 0xff; crcstart = (crcstart >>> 8) ^ this.crctable[index]; } return index; } getcrcindex(t) { for (let i = 0; i < 256; i++) if (this.crctable[i] >>> 24 == t) return i; return -1; } deepCheck(i, index) { let tc = 0x00, str = '', hash = this.crc32(i); tc = hash & 0xff ^ index[2]; if (!(tc <= 57 && tc >= 48)) return [0]; str += tc - 48; hash = this.crctable[index[2]] ^ (hash >>> 8); tc = hash & 0xff ^ index[1]; if (!(tc <= 57 && tc >= 48)) return [0]; str += tc - 48; hash = this.crctable[index[1]] ^ (hash >>> 8); tc = hash & 0xff ^ index[0]; if (!(tc <= 57 && tc >= 48)) return [0]; str += tc - 48; hash = this.crctable[index[0]] ^ (hash >>> 8); return [1, str]; } } { const crc = new Midcrc(); API.midcrc = input => crc.run(input); API.crc32 = input => (((crc.crc32(input) + 1) * -1) >>> 0).toString(16); } //# sourceURL=API://@Bilibili-Old/lib/crc32.js`; /*!***********************!*/ /**/modules["cubicBezier.js"] = /*** ./dist/lib/cubicBezier.js ***/ `{ const NEWTON_ITERATIONS = 4; const NEWTON_MIN_SLOPE = 0.001; const SUBDIVISION_PRECISION = 0.0000001; const SUBDIVISION_MAX_ITERATIONS = 10; const kSplineTableSize = 11; const kSampleStepSize = 1.0 / (kSplineTableSize - 1.0); const float32ArraySupported = typeof Float32Array === 'function'; function A(aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; } function B(aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; } function C(aA1) { return 3.0 * aA1; } // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2. function calcBezier(aT, aA1, aA2) { return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT; } // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2. function getSlope(aT, aA1, aA2) { return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1); } function binarySubdivide(aX, aA, aB, mX1, mX2) { let currentX, currentT, i = 0; do { currentT = aA + (aB - aA) / 2.0; currentX = calcBezier(currentT, mX1, mX2) - aX; if (currentX > 0.0) { aB = currentT; } else { aA = currentT; } } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS); return currentT; } function newtonRaphsonIterate(aX, aGuessT, mX1, mX2) { for (let i = 0; i < NEWTON_ITERATIONS; ++i) { const currentSlope = getSlope(aGuessT, mX1, mX2); if (currentSlope === 0.0) { return aGuessT; } const currentX = calcBezier(aGuessT, mX1, mX2) - aX; aGuessT -= currentX / currentSlope; } return aGuessT; } function LinearEasing(x) { return x; } API.bezier = function (mX1, mY1, mX2, mY2) { if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) { throw new Error('bezier x values must be in [0, 1] range'); } if (mX1 === mY1 && mX2 === mY2) { return LinearEasing; } // Precompute samples table const sampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize); for (let i = 0; i < kSplineTableSize; ++i) { sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2); } function getTForX(aX) { let intervalStart = 0.0; let currentSample = 1; const lastSample = kSplineTableSize - 1; for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) { intervalStart += kSampleStepSize; } --currentSample; // Interpolate to provide an initial guess for t const dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]); const guessForT = intervalStart + dist * kSampleStepSize; const initialSlope = getSlope(guessForT, mX1, mX2); if (initialSlope >= NEWTON_MIN_SLOPE) { return newtonRaphsonIterate(aX, guessForT, mX1, mX2); } else if (initialSlope === 0.0) { return guessForT; } else { return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2); } } return function BezierEasing(x) { // Because JavaScript number are imprecise, we should guarantee the extremes are right. if (x === 0 || x === 1) { return x; } return calcBezier(getTForX(x), mY1, mY2); }; }; } //# sourceURL=API://@Bilibili-Old/lib/cubicBezier.js`; /*!***********************!*/ /**/modules["md5.js"] = /*** ./dist/lib/md5.js ***/ `{ const ERROR = 'input is invalid type'; const ARRAY_BUFFER = true; const HEX_CHARS = '0123456789abcdef'.split(''); const EXTRA = [128, 32768, 8388608, -2147483648]; const SHIFT = [0, 8, 16, 24]; const OUTPUT_TYPES = ['hex', 'array', 'digest', 'buffer', 'arrayBuffer', 'base64']; const BASE64_ENCODE_CHAR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); let buffer = new ArrayBuffer(68), blocks = new Uint32Array(buffer), buffer8 = new Uint8Array(buffer); let createOutputMethod = function (outputType) { return function (message) { return new Md5(true).update(message)[outputType](); }; }; let createMethod = function () { let method = createOutputMethod('hex'); method.create = function () { return new Md5(); }; method.update = function (message) { return method.create().update(message); }; for (let i = 0; i < OUTPUT_TYPES.length; ++i) { let type = OUTPUT_TYPES[i]; method[type] = createOutputMethod(type); } return method; }; class Md5 { blocks; buffer8 = new Uint8Array(); h0 = 0; h1 = 0; h2 = 0; h3 = 0; start = 0; bytes = 0; hBytes = 0; finalized = false; hashed = false; first = true; array; buffer; lastByteIndex = 0; constructor(sharedMemory) { if (sharedMemory) { blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] = blocks[4] = blocks[5] = blocks[6] = blocks[7] = blocks[8] = blocks[9] = blocks[10] = blocks[11] = blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0; this.blocks = blocks; this.buffer8 = buffer8; } else { if (ARRAY_BUFFER) { let buffer = new ArrayBuffer(68); this.buffer8 = new Uint8Array(buffer); this.blocks = new Uint32Array(buffer); } else { this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; } } this.toString = this.hex; this.array = this.digest; this.buffer = this.arrayBuffer; } update(message) { if (this.finalized) { return; } message = typeof message === 'number' ? message + '' : message; let notString, type = typeof message; if (type !== 'string') { if (type === 'object') { if (message === null) { throw ERROR; } else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) { message = new Uint8Array(message); } else if (!Array.isArray(message)) { if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) { throw ERROR; } } } else { throw ERROR; } notString = true; } let code, index = 0, i, length = message.length, blocks = this.blocks; let buffer8 = this.buffer8; while (index < length) { if (this.hashed) { this.hashed = false; blocks[0] = blocks[16]; blocks[16] = blocks[1] = blocks[2] = blocks[3] = blocks[4] = blocks[5] = blocks[6] = blocks[7] = blocks[8] = blocks[9] = blocks[10] = blocks[11] = blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0; } if (notString) { if (ARRAY_BUFFER) { for (i = this.start; index < length && i < 64; ++index) { buffer8[i++] = message[index]; } } else { for (i = this.start; index < length && i < 64; ++index) { blocks[i >> 2] |= message[index] << SHIFT[i++ & 3]; } } } else { if (ARRAY_BUFFER) { for (i = this.start; index < length && i < 64; ++index) { code = message.charCodeAt(index); if (code < 0x80) { buffer8[i++] = code; } else if (code < 0x800) { buffer8[i++] = 0xc0 | (code >> 6); buffer8[i++] = 0x80 | (code & 0x3f); } else if (code < 0xd800 || code >= 0xe000) { buffer8[i++] = 0xe0 | (code >> 12); buffer8[i++] = 0x80 | ((code >> 6) & 0x3f); buffer8[i++] = 0x80 | (code & 0x3f); } else { code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff)); buffer8[i++] = 0xf0 | (code >> 18); buffer8[i++] = 0x80 | ((code >> 12) & 0x3f); buffer8[i++] = 0x80 | ((code >> 6) & 0x3f); buffer8[i++] = 0x80 | (code & 0x3f); } } } else { for (i = this.start; index < length && i < 64; ++index) { code = message.charCodeAt(index); if (code < 0x80) { blocks[i >> 2] |= code << SHIFT[i++ & 3]; } else if (code < 0x800) { blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3]; blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; } else if (code < 0xd800 || code >= 0xe000) { blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3]; blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; } else { code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff)); blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3]; blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3]; blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3]; blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3]; } } } } this.lastByteIndex = i; this.bytes += i - this.start; if (i >= 64) { this.start = i - 64; this.hash(); this.hashed = true; } else { this.start = i; } } if (this.bytes > 4294967295) { this.hBytes += this.bytes / 4294967296 << 0; this.bytes = this.bytes % 4294967296; } return this; } finalize() { if (this.finalized) { return; } this.finalized = true; let blocks = this.blocks, i = this.lastByteIndex; blocks[i >> 2] |= EXTRA[i & 3]; if (i >= 56) { if (!this.hashed) { this.hash(); } blocks[0] = blocks[16]; blocks[16] = blocks[1] = blocks[2] = blocks[3] = blocks[4] = blocks[5] = blocks[6] = blocks[7] = blocks[8] = blocks[9] = blocks[10] = blocks[11] = blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0; } blocks[14] = this.bytes << 3; blocks[15] = this.hBytes << 3 | this.bytes >>> 29; this.hash(); } hash() { let a, b, c, d, bc, da, blocks = this.blocks; if (this.first) { a = blocks[0] - 680876937; a = (a << 7 | a >>> 25) - 271733879 << 0; d = (-1732584194 ^ a & 2004318071) + blocks[1] - 117830708; d = (d << 12 | d >>> 20) + a << 0; c = (-271733879 ^ (d & (a ^ -271733879))) + blocks[2] - 1126478375; c = (c << 17 | c >>> 15) + d << 0; b = (a ^ (c & (d ^ a))) + blocks[3] - 1316259209; b = (b << 22 | b >>> 10) + c << 0; } else { a = this.h0; b = this.h1; c = this.h2; d = this.h3; a += (d ^ (b & (c ^ d))) + blocks[0] - 680876936; a = (a << 7 | a >>> 25) + b << 0; d += (c ^ (a & (b ^ c))) + blocks[1] - 389564586; d = (d << 12 | d >>> 20) + a << 0; c += (b ^ (d & (a ^ b))) + blocks[2] + 606105819; c = (c << 17 | c >>> 15) + d << 0; b += (a ^ (c & (d ^ a))) + blocks[3] - 1044525330; b = (b << 22 | b >>> 10) + c << 0; } a += (d ^ (b & (c ^ d))) + blocks[4] - 176418897; a = (a << 7 | a >>> 25) + b << 0; d += (c ^ (a & (b ^ c))) + blocks[5] + 1200080426; d = (d << 12 | d >>> 20) + a << 0; c += (b ^ (d & (a ^ b))) + blocks[6] - 1473231341; c = (c << 17 | c >>> 15) + d << 0; b += (a ^ (c & (d ^ a))) + blocks[7] - 45705983; b = (b << 22 | b >>> 10) + c << 0; a += (d ^ (b & (c ^ d))) + blocks[8] + 1770035416; a = (a << 7 | a >>> 25) + b << 0; d += (c ^ (a & (b ^ c))) + blocks[9] - 1958414417; d = (d << 12 | d >>> 20) + a << 0; c += (b ^ (d & (a ^ b))) + blocks[10] - 42063; c = (c << 17 | c >>> 15) + d << 0; b += (a ^ (c & (d ^ a))) + blocks[11] - 1990404162; b = (b << 22 | b >>> 10) + c << 0; a += (d ^ (b & (c ^ d))) + blocks[12] + 1804603682; a = (a << 7 | a >>> 25) + b << 0; d += (c ^ (a & (b ^ c))) + blocks[13] - 40341101; d = (d << 12 | d >>> 20) + a << 0; c += (b ^ (d & (a ^ b))) + blocks[14] - 1502002290; c = (c << 17 | c >>> 15) + d << 0; b += (a ^ (c & (d ^ a))) + blocks[15] + 1236535329; b = (b << 22 | b >>> 10) + c << 0; a += (c ^ (d & (b ^ c))) + blocks[1] - 165796510; a = (a << 5 | a >>> 27) + b << 0; d += (b ^ (c & (a ^ b))) + blocks[6] - 1069501632; d = (d << 9 | d >>> 23) + a << 0; c += (a ^ (b & (d ^ a))) + blocks[11] + 643717713; c = (c << 14 | c >>> 18) + d << 0; b += (d ^ (a & (c ^ d))) + blocks[0] - 373897302; b = (b << 20 | b >>> 12) + c << 0; a += (c ^ (d & (b ^ c))) + blocks[5] - 701558691; a = (a << 5 | a >>> 27) + b << 0; d += (b ^ (c & (a ^ b))) + blocks[10] + 38016083; d = (d << 9 | d >>> 23) + a << 0; c += (a ^ (b & (d ^ a))) + blocks[15] - 660478335; c = (c << 14 | c >>> 18) + d << 0; b += (d ^ (a & (c ^ d))) + blocks[4] - 405537848; b = (b << 20 | b >>> 12) + c << 0; a += (c ^ (d & (b ^ c))) + blocks[9] + 568446438; a = (a << 5 | a >>> 27) + b << 0; d += (b ^ (c & (a ^ b))) + blocks[14] - 1019803690; d = (d << 9 | d >>> 23) + a << 0; c += (a ^ (b & (d ^ a))) + blocks[3] - 187363961; c = (c << 14 | c >>> 18) + d << 0; b += (d ^ (a & (c ^ d))) + blocks[8] + 1163531501; b = (b << 20 | b >>> 12) + c << 0; a += (c ^ (d & (b ^ c))) + blocks[13] - 1444681467; a = (a << 5 | a >>> 27) + b << 0; d += (b ^ (c & (a ^ b))) + blocks[2] - 51403784; d = (d << 9 | d >>> 23) + a << 0; c += (a ^ (b & (d ^ a))) + blocks[7] + 1735328473; c = (c << 14 | c >>> 18) + d << 0; b += (d ^ (a & (c ^ d))) + blocks[12] - 1926607734; b = (b << 20 | b >>> 12) + c << 0; bc = b ^ c; a += (bc ^ d) + blocks[5] - 378558; a = (a << 4 | a >>> 28) + b << 0; d += (bc ^ a) + blocks[8] - 2022574463; d = (d << 11 | d >>> 21) + a << 0; da = d ^ a; c += (da ^ b) + blocks[11] + 1839030562; c = (c << 16 | c >>> 16) + d << 0; b += (da ^ c) + blocks[14] - 35309556; b = (b << 23 | b >>> 9) + c << 0; bc = b ^ c; a += (bc ^ d) + blocks[1] - 1530992060; a = (a << 4 | a >>> 28) + b << 0; d += (bc ^ a) + blocks[4] + 1272893353; d = (d << 11 | d >>> 21) + a << 0; da = d ^ a; c += (da ^ b) + blocks[7] - 155497632; c = (c << 16 | c >>> 16) + d << 0; b += (da ^ c) + blocks[10] - 1094730640; b = (b << 23 | b >>> 9) + c << 0; bc = b ^ c; a += (bc ^ d) + blocks[13] + 681279174; a = (a << 4 | a >>> 28) + b << 0; d += (bc ^ a) + blocks[0] - 358537222; d = (d << 11 | d >>> 21) + a << 0; da = d ^ a; c += (da ^ b) + blocks[3] - 722521979; c = (c << 16 | c >>> 16) + d << 0; b += (da ^ c) + blocks[6] + 76029189; b = (b << 23 | b >>> 9) + c << 0; bc = b ^ c; a += (bc ^ d) + blocks[9] - 640364487; a = (a << 4 | a >>> 28) + b << 0; d += (bc ^ a) + blocks[12] - 421815835; d = (d << 11 | d >>> 21) + a << 0; da = d ^ a; c += (da ^ b) + blocks[15] + 530742520; c = (c << 16 | c >>> 16) + d << 0; b += (da ^ c) + blocks[2] - 995338651; b = (b << 23 | b >>> 9) + c << 0; a += (c ^ (b | ~d)) + blocks[0] - 198630844; a = (a << 6 | a >>> 26) + b << 0; d += (b ^ (a | ~c)) + blocks[7] + 1126891415; d = (d << 10 | d >>> 22) + a << 0; c += (a ^ (d | ~b)) + blocks[14] - 1416354905; c = (c << 15 | c >>> 17) + d << 0; b += (d ^ (c | ~a)) + blocks[5] - 57434055; b = (b << 21 | b >>> 11) + c << 0; a += (c ^ (b | ~d)) + blocks[12] + 1700485571; a = (a << 6 | a >>> 26) + b << 0; d += (b ^ (a | ~c)) + blocks[3] - 1894986606; d = (d << 10 | d >>> 22) + a << 0; c += (a ^ (d | ~b)) + blocks[10] - 1051523; c = (c << 15 | c >>> 17) + d << 0; b += (d ^ (c | ~a)) + blocks[1] - 2054922799; b = (b << 21 | b >>> 11) + c << 0; a += (c ^ (b | ~d)) + blocks[8] + 1873313359; a = (a << 6 | a >>> 26) + b << 0; d += (b ^ (a | ~c)) + blocks[15] - 30611744; d = (d << 10 | d >>> 22) + a << 0; c += (a ^ (d | ~b)) + blocks[6] - 1560198380; c = (c << 15 | c >>> 17) + d << 0; b += (d ^ (c | ~a)) + blocks[13] + 1309151649; b = (b << 21 | b >>> 11) + c << 0; a += (c ^ (b | ~d)) + blocks[4] - 145523070; a = (a << 6 | a >>> 26) + b << 0; d += (b ^ (a | ~c)) + blocks[11] - 1120210379; d = (d << 10 | d >>> 22) + a << 0; c += (a ^ (d | ~b)) + blocks[2] + 718787259; c = (c << 15 | c >>> 17) + d << 0; b += (d ^ (c | ~a)) + blocks[9] - 343485551; b = (b << 21 | b >>> 11) + c << 0; if (this.first) { this.h0 = a + 1732584193 << 0; this.h1 = b - 271733879 << 0; this.h2 = c - 1732584194 << 0; this.h3 = d + 271733878 << 0; this.first = false; } else { this.h0 = this.h0 + a << 0; this.h1 = this.h1 + b << 0; this.h2 = this.h2 + c << 0; this.h3 = this.h3 + d << 0; } } hex() { this.finalize(); let h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3; return HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] + HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] + HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] + HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] + HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] + HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] + HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] + HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] + HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] + HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] + HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] + HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] + HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] + HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] + HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] + HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F]; } digest() { this.finalize(); let h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3; return [ h0 & 0xFF, (h0 >> 8) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 24) & 0xFF, h1 & 0xFF, (h1 >> 8) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 24) & 0xFF, h2 & 0xFF, (h2 >> 8) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 24) & 0xFF, h3 & 0xFF, (h3 >> 8) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 24) & 0xFF ]; } arrayBuffer() { this.finalize(); let buffer = new ArrayBuffer(16); let blocks = new Uint32Array(buffer); blocks[0] = this.h0; blocks[1] = this.h1; blocks[2] = this.h2; blocks[3] = this.h3; return buffer; } base64() { let i, v1, v2, v3, base64Str = '', bytes = this.array(); for (i = 0; i < 15;) { v1 = bytes[i++]; v2 = bytes[i++]; v3 = bytes[i++]; base64Str += BASE64_ENCODE_CHAR[v1 >>> 2] + BASE64_ENCODE_CHAR[(v1 << 4 | v2 >>> 4) & 63] + BASE64_ENCODE_CHAR[(v2 << 2 | v3 >>> 6) & 63] + BASE64_ENCODE_CHAR[v3 & 63]; } v1 = bytes[i]; base64Str += BASE64_ENCODE_CHAR[v1 >>> 2] + BASE64_ENCODE_CHAR[(v1 << 4) & 63] + '=='; return base64Str; } } API.md5 = createMethod(); } //# sourceURL=API://@Bilibili-Old/lib/md5.js`; /*!***********************!*/ /**/modules["sign.js"] = /*** ./dist/lib/sign.js ***/ `class Sign { static table = [ "rbMCKn@KuamXWlPMoJGsKcbiJKUfkPF_8dABscJntvqhRSETg", "/a_206b\`_.61.bca6117.175bcdadc41850c010c..././1\`\`", "157bdd\`6/bc73632.bcd660baa03a.43841211032b5c4\`6b/", "351a7a6b/.b\`d77da1cdccc25_13bc0a81a6d63.7ad13\`c50", "4_/54d\`3_4_73..2c42\`d4.a3__31b358d706d\`._7a.3_b5.", "12a.7c4b76c.a\`12bb4\`2b2b275c667c85b6d\`c_c\`0d5.051", "bb16d652\`04.7/121d3474b_2.c12\`7386\`0/bdd6ca0c7.22", "244_530/7/.ab\`7.//22a15572502b_08c21./_.\`3164\`c36", "16_d52_d/d22_2c0a.6573355/b\`./bd8a\`bc6114a30_4.\`d", "c02ba/d6.33d05cb/5d34.7d_23_\`_2785\`c60.a\`.4343726", "2aa2\`.1_\`_1.73\`.70.67d.bc671c16382a3d\`71a4.bcb3c7", "40/171b046c/bcc0a603ac620\`372ba_8d706d\`._7a.3_b5.", "c4_a.7562_15\`_a416a/63/c2cbcb\`308a/\`//41b30376.b5" // 7d08...1b1c ]; static keySecret; /** * 签名URL * @param url 原URL * @param obj 添加到URL上的查询参数对象,可选 * @param id appkey在\`keySecret\`中的索引 * @returns 签名后的URL */ static sign(url, obj = {}, id = 0) { this.keySecret = this.decode(id); obj = { ...Format.urlObj(url), ...obj }; url = url.split("#")[0].split("?")[0]; delete obj.sign; obj.appkey = this.keySecret[0]; const table = Object.keys(obj).sort().reduce((s, d) => { s[d] = obj[d]; return s; }, {}); table.sign = id === 3 && table.api ? (API.md5(Format.objUrl("", { api: decodeURIComponent(table.api) }) + this.keySecret[1])) : (API.md5(Format.objUrl("", table) + this.keySecret[1])); return Format.objUrl(url, table); } /** * 提取appkey和盐 * @param id appkey在\`keySecret\`中的索引 * @returns [appkey, sort] */ static decode(id) { if (typeof id === "number") { id = id < this.table.length ? id : 0; return this.table[id].split("").reverse().reduce((s, d) => { s = s + String.fromCharCode(d.charCodeAt(0) + 2); return s; }, '').split(":"); } else { return [id, this.list()[id]]; } } /** * 生成\`keySecret\`池 * @param key appkey * @param secret appkey对应的盐 * @returns 混淆后的字符串 */ static encode(key, secret) { return (key + ":" + secret).split("").reverse().reduce((s, d) => { s = s + String.fromCharCode(d.charCodeAt(0) - 2); return s; }, ""); } /** * 输出\`keySecret\`池对象 * @returns \`keySecret\`池对象 */ static list() { return this.table.reduce((s, d, i) => { let keySecret = this.decode(i); s[keySecret[0]] = keySecret[1]; return s; }, {}); } } API.urlsign = ((url, obj = {}, id = 0) => Sign.sign(url, obj, id)); API.urlsign.getKeyById = (id) => Sign.decode(id); API.urlsign.encode = (key, secret) => Sign.encode(key, secret); API.urlsign.list = () => Sign.list(); //# sourceURL=API://@Bilibili-Old/lib/sign.js`; /*!***********************!*/ /**/modules["anime.js"] = /*** ./dist/url/anime.js ***/ `class Anime extends API.rewrite { constructor(html) { super(html); this.script = [ { type: "text/javascript", src: "//static.hdslb.com/js/jquery.min.js" }, { type: "text/javascript", src: "//s1.hdslb.com/bfs/seed/jinkela/header/header.js" }, { type: "text/javascript", src: "//s2.hdslb.com/bfs/cm/st/bundle.js" }, { type: "text/javascript", src: "//static.hdslb.com/js/promise.auto.min.js" }, { type: "text/javascript", src: "//www.bilibili.com/gentleman/polyfill.js?features=Promise%2CObject.assign%2CString.prototype.includes%2CNumber.isNaN" }, { type: "text/javascript", src: "//s1.hdslb.com/bfs/static/ogv/fe/iris.min.js" }, { src: "//s1.hdslb.com/bfs/static/bangumi-home/1.bangumi-home.73141fb5868615cb4fe6bc969ccd02cb7c1c7d4c.js", crossorigin: "", defer: "defer" }, { src: "//s1.hdslb.com/bfs/static/bangumi-home/bangumi-home.73141fb5868615cb4fe6bc969ccd02cb7c1c7d4c.js", crossorigin: "", defer: "defer" }, { type: "text/javascript", charset: "utf-8", src: "//static.hdslb.com/common/js/footer.js" } ]; API.path.name = "anime"; this.flushDocument(); } } new Anime("anime.html"); //# sourceURL=API://@Bilibili-Old/url/anime.js`; /*!***********************!*/ /**/modules["bnj.js"] = /*** ./dist/url/bnj.js ***/ `API.runWhile(() => window.__INITIAL_STATE__, () => { try { const titles = window.__INITIAL_STATE__.videoSections.reduce((s, d) => { d.episodes.forEach(d => s.push(d)); return s; }, []); // 替换播放器节点 const node = document.querySelector("#bilibili-player").parentElement; const root = node.attachShadow({ mode: "closed" }); // 使用shadow覆盖视频节点而不影响页面其他功能 const iframe = document.createElement('iframe'); iframe.src = \`https://www.bilibili.com/blackboard/html5player.html?aid=\${window.__INITIAL_STATE__.videoInfo.aid}&cid=\${window.__INITIAL_STATE__.videoInfo.cid}&enable_ssl=1&crossDomain=1&as_wide=1\`; iframe.setAttribute("style", "width: 906px; height: 556px;border:none;"); root.appendChild(iframe); // 添加时间戳监听 const episodes = document.querySelectorAll('.video-episode-card__info-title'); episodes.forEach((d, i, e) => { const episode = titles.find(t => t.title == d.innerText); e[i].parentNode.parentNode.onclick = () => { setTimeout(() => { // 销毁切p播放器已阻止自动播放 window.player && window.player.destroy(); }, 100); // toast(episode.title, \`av\${Reflect.get(episode, "aid")}\`, \`UP主:\${Reflect.get(episode, "author").name}\`) iframe.contentWindow.postMessage({ ...episode }); }; }); window.addEventListener("message", e => { if (e.data == "MediaMeta") { const episode = titles.find(t => t.aid == window.__INITIAL_STATE__.videoInfo.aid); iframe.contentWindow.postMessage({ title: episode.title, author: episode.author, cover: episode.cover }); } }); // 销毁原播放器 API.runWhile(() => window.player && window.player.destroy, () => { setTimeout(() => { window.player && window.player.destroy(); }, 100); }); } catch (e) { toast.error("bnjFestival.js", e); } }); //# sourceURL=API://@Bilibili-Old/url/bnj.js`; /*!***********************!*/ /**/modules["history.js"] = /*** ./dist/url/history.js ***/ `{ config.history && API.xhrhook(["api.bilibili.com/x/web-interface/history/cursor", "business"], function (args) { let obj = Format.urlObj(args[1]), max = obj.max || "", view_at = obj.view_at || ""; args[1] = Format.objUrl("//api.bilibili.com/x/web-interface/history/cursor", { max: max, view_at: view_at, type: "archive", ps: "20" }); }, undefined, false); config.searchHistory && API.runWhile(() => document.querySelector(".b-head-search"), () => document.querySelector(".b-head-search")?.remove()); } //# sourceURL=API://@Bilibili-Old/url/history.js`; /*!***********************!*/ /**/modules["medialist.js"] = /*** ./dist/url/medialist.js ***/ `class Playlist extends API.rewrite { route = Format.urlObj(location.href); type = 3; pl = /\\d+/.exec(API.path[5]) && Number(/\\d+/.exec(API.path[5])[0]); playlist = Boolean(API.path[5].startsWith("pl")); oid = ""; toview = { "attr": 2, "count": 100, "cover": "https://i0.hdslb.com/bfs/archive/a45ef4fcde397247032cf4ce0c8f71815f9e28d0.jpg", "ctime": 1529021131, "description": "bilibili moe 2018 动画角色人气大赏日本动画场应援视频播单 / 每天不定时更新最新的一批", "faved_count": 0, "favored": 0, "favorite": false, "id": 1826036, "is_favorite": false, "like_count": 0, "list": [], "mid": 26468955, "mlid": 182603655, "mtime": 1533874759, "name": "bilibili moe 2018 日本动画场应援", "owner": { "face": "http://i2.hdslb.com/bfs/face/57389d533621407d36981a99fed93834dd8b20e6.jpg", "mid": 26468955, "name": "萌战基" }, "pid": 769, "play_count": 0, "recent_oids": [], "recent_res": [], "reply_count": 0, "share_count": 0, "stat": { "favorite": 1685, "pid": 769, "reply": 10, "share": 0, "view": 298928 }, "state": 0, "type": 2 }; has_more = false; observer = new MutationObserver(d => this.Observer(d)); constructor(html) { super(html); this.initPlayerQueryData(); history.replaceState(null, null, \`https://www.bilibili.com/playlist/video/pl\${this.pl}\`); this.script = [ { type: "text/javascript", src: "//s1.hdslb.com/bfs/static/jinkela/long/js/jquery/jquery1.7.2.min.js" }, { type: "text/javascript", src: "//static.hdslb.com/js/jquery.qrcode.min.js" }, { type: "text/javascript", src: "//s1.hdslb.com/bfs/seed/jinkela/header/header.js" }, { type: "text/javascript", src: "//static.hdslb.com/common/js/footer.js" }, { type: "text/javascript", src: "//static.hdslb.com/js/swfobject.js" }, { type: "text/javascript", src: "//static.hdslb.com/mstation/js/upload/moxie.js" }, { type: "text/javascript", src: "//static.hdslb.com/mstation/js/upload/plupload.js" }, { type: "text/javascript", src: "//static.hdslb.com/phoenix/dist/js/comment.min.js" }, { type: "text/javascript", src: "//s1.hdslb.com/bfs/static/jinkela/playlist-video/1.playlist_video.87292febba67b03f65d05c15d03e325d9db4f56a.js" }, { type: "text/javascript", src: "//s1.hdslb.com/bfs/static/jinkela/playlist-video/playlist_video.87292febba67b03f65d05c15d03e325d9db4f56a.js" } ]; API.jsonphookasync("toview", undefined, async (url) => { history.replaceState(null, null, API.path.join("/")); try { if (this.playlist || this.pl === 182603655) { const result = await xhr({ url: "https://cdn.jsdelivr.net/gh/MotooriKashin/Bilibili-Old/Json/pl769.json", responseType: "json" }); this.toview = result.data; return result; } else { const rqs = await Promise.all([ xhr.get(\`https://api.bilibili.com/x/v1/medialist/info?type=\${this.type}&biz_id=\${this.pl}&tid=0\`, { responseType: "json" }), xhr.get(\`https://api.bilibili.com/x/v2/medialist/resource/list?type=\${this.type}&oid=\${this.oid}&otype=2&biz_id=\${this.pl}&bvid=&with_current=true&mobi_app=web&ps=20&direction=false&sort_field=1&tid=0&desc=true\`, { responseType: "json" }) ]); this.info(rqs[0]); this.list(rqs[1]); return { code: 0, data: this.toview, message: "0", ttl: 1 }; } } catch (e) { toast.error("获取medialist数据失败!请刷新页面或者在脚本设置中关闭重构“medialist”选项"); throw e; } }); API.switchVideo(() => { const data = this.toview.list.find(d => d.aid == API.aid); if (data) { API.tid = data.tid; API.mediaSession({ title: data.pages.find(d => d.cid == API.cid).part || data.title, artist: data.owner.name, album: data.title, artwork: [{ src: data.pic }] }); (Reflect.has(data, "attr") && !!+data.attr.toString(2)[data.attr.toString(2).length - 2] && toast.warning("限制视频,可能无法在播单中直接播放~")); } if (this.has_more) { API.runWhile(() => document.querySelector(".bilibili-player-playlist-item"), () => this.startObserver()); } }); this.flushDocument(); this.onload = () => this.afterFlush(); } initPlayerQueryData() { if (this.route.business) switch (this.route.business) { case "space": this.type = 1; break; case "space_series": this.type = 5; this.pl = this.route.business_id; break; case "space_channel": this.type = 6; this.pl = 10 * this.route.business_id + this.pl % 10; break; case "space_collection": this.type = 8; this.pl = this.route.business_id; break; default: this.type = 3; } } startObserver() { this.observer.observe(document.querySelector(".bilibili-player-playlist-item").parentElement.parentElement, { attributes: true }); } info(obj) { this.toview.attr = obj.data.attr; this.toview.count = obj.data.media_count; this.toview.cover = obj.data.cover; this.toview.ctime = obj.data.ctime; this.toview.description = obj.data.intro; this.toview.favored = obj.data.fav_state; this.toview.favorite = Boolean(obj.data.fav_state); this.toview.id = obj.data.id; this.toview.is_favorite = Boolean(obj.data.fav_state); this.toview.like_count = obj.data.like_state; this.toview.mid = obj.data.mid; this.toview.mlid = obj.data.id; this.toview.mtime = obj.data.ctime; this.toview.name = obj.data.title; this.toview.owner = obj.data.upper; this.toview.pid = obj.data.id; this.toview.stat.favorite = obj.data.cnt_info.collect; this.toview.stat.pid = obj.data.id; this.toview.stat.reply = obj.data.cnt_info.reply; this.toview.stat.share = obj.data.cnt_info.share; this.toview.stat.view = obj.data.cnt_info.play; } list(obj) { obj.data.media_list.reduce((s, d) => { s.push({ aid: d.id, attr: d.attr, attribute: 0, cid: d.pages[0].id, copyright: d.copy_right, ctime: d.pubtime, desc: d.intro, dimension: d.pages[0].dimension, duration: d.duration, dynamic: "", owner: d.upper, pages: d.pages.reduce((s, b) => { s.push({ cid: b.id, dimension: b.dimension, duration: b.duration, from: b.from, page: b.page, part: b.title, vid: "", weblink: b.link }); return s; }, []), pic: d.cover, pubdate: d.pubtime, rights: d.rights, stat: { aid: d.id, coin: d.cnt_info.coin, danmaku: d.cnt_info.danmaku, dislike: d.cnt_info.thumb_down, favorite: d.cnt_info.collect, his_rank: 0, like: d.cnt_info.thumb_up, now_rank: 0, reply: d.cnt_info.reply, share: d.cnt_info.share, view: d.cnt_info.play }, state: 0, tid: d.tid, title: d.title, tname: "", videos: d.page }); return s; }, this.toview.list); this.has_more = obj.data.has_more; this.oid = this.toview.list[this.toview.list.length - 1].aid; } afterFlush() { API.runWhile(() => document.getElementsByClassName("bili-header-m")[1], () => document.getElementsByClassName("bili-header-m")[1].remove()); // 移除上古顶栏 if (this.playlist && !(this.pl == 769)) { history.replaceState(null, null, \`https://www.bilibili.com/playlist/video/pl769\`); toast.warning("原生playlist页面已无法访问,已重定向到脚本备份的pl769~"); } if (document.compatMode === "BackCompat") { // 怪异模式下样式修复 API.addCss(".bili-header-m .nav-menu .profile-info .i-face { top:5px; }"); } API.importModule("descBV.js"); // 修复简介中超链接 API.importModule("videoSort.js"); // 修正分区信息 config.enlike && API.importModule("enLike.js"); // 添加点赞功能 config.electric && API.jsonphook("api.bilibili.com/x/web-interface/elec/show", url => Format.objUrl(url, { aid: 1, mid: 1 })); } Observer(record) { record.forEach(d => { this.calcScroll(d.target); }); } calcScroll(node) { const maxHeight = node.scrollHeight; const scroll = /\\d+/.exec(node.style.top) ? Number(/\\d+/.exec(node.style.top)) : 0; if (node.className.includes("hidden")) return; if (maxHeight - scroll > 0 && maxHeight - scroll < 600) { this.observer.disconnect(); // 暂停监听 toast("loading..."); xhr.get(\`https://api.bilibili.com/x/v2/medialist/resource/list?type=\${this.type}&oid=\${this.oid}&otype=2&biz_id=\${this.pl}&bvid=&with_current=true&mobi_app=web&ps=20&direction=false&sort_field=1&tid=0&desc=true\`, { responseType: "json" }).then(d => { this.formatMore(d); this.has_more && this.startObserver(); // 重新监听 }).catch(e => { toast.error("正在加载...", e); }); } } formatMore(obj) { const result = obj.data.media_list.reduce((s, d) => { s.push({ ao: d.rights && d.rights.pay, Sz: d.upper && d.upper.face, Te: d.pages.reduce((s, f) => { s.push({ Da: d.bangumi?.ep_id, Fb: d.bangumi?.season?.season_id, aid: d.id, duration: f.duration, from: f.from, j: f.id, ni: f.title, page: f.page }); return s; }, []), Tz: d.upper && d.upper.mid, aid: d.id, duration: d.duration, ko: d.upper && d.upper.name, lb: d.cover, state: 0, title: d.title, }); return s; }, []); this.list(obj); this.has_more ? window.player?.updatePlaylist(result) : toast.warning("没有更多了!"); } } new Playlist("playlist.html"); //# sourceURL=API://@Bilibili-Old/url/medialist.js`; /*!***********************!*/ /**/modules["player.js"] = /*** ./dist/url/player.js ***/ `class Player extends API.rewrite { obj = Format.urlObj(location.href); aid = this.obj.aid || this.obj.avid; bvid = this.obj.bvid; cid = this.obj.cid; constructor(html) { super(html); this.script = [ { type: "text/javascript", src: "//static.hdslb.com/js/jquery.min.js" }, { type: "text/javascript", src: "//static.hdslb.com/js/jquery.qrcode.min.js" }, { type: "text/javascript", src: "//static.hdslb.com/player/js/whitelist.js" } ]; API.path.name = "player"; this.flushDocument(); this.onload = () => { this.afterFlush(); }; } async afterFlush() { if (!Number(this.aid)) { if (this.obj.aid) this.aid = API.abv(this.aid); else if (this.bvid) this.aid = API.abv(this.bvid); } if (!Number(this.cid)) { this.obj = (await API.urlInputCheck(location.href)); this.aid = this.obj.aid; this.cid = this.obj.cid; if (!Number(this.cid)) return toast.error("初始化嵌入式播放器失败!", this.obj); } const playerParam = { aid: this.aid, cid: this.cid, p: API.getUrlValue("P"), // autoplay: API.getUrlValue("autoplay"), 深恶痛绝 as_wide: API.getUrlValue("as_wide"), bnj: API.getUrlValue("bnj"), player_type: API.getUrlValue("player_type"), season_type: API.getUrlValue("season_type") }; if (this.obj.pgc || this.obj.ssid || this.obj.epid) { playerParam["seasonId"] = this.obj.ssid; playerParam["episodeId"] = this.obj.epid; playerParam["urlparam"] = \`module%3Dbangumi%26season_type%3D\${playerParam.season_type}\`; } window.EmbedPlayer("player", "//static.hdslb.com/play.swf", Format.objUrl("", playerParam)); window.addEventListener('message', e => { if (e.data.aid) { window.__playinfo__ = undefined; e.data.as_wide = 1; e.data.dashSymbol = true; e.data.p = 1; e.data.pre_ad = ""; // history.replaceState(undefined, undefined, Format.objUrl("https://www.bilibili.com/blackboard/html5player.html", { aid: e.data.aid, cid: e.data.cid })); window.player.destroy(); window.player = new window.BilibiliPlayer(e.data); } if (e.data.title) { API.mediaSession({ title: e.data.title, artist: e.data.author?.name, album: document.title, artwork: [{ src: e.data.cover }] }); } }); window.parent.postMessage("MediaMeta"); } } new Player("player.html"); //# sourceURL=API://@Bilibili-Old/url/player.js`; /*!***********************!*/ /**/modules["ranking.js"] = /*** ./dist/url/ranking.js ***/ `class Ranking extends API.rewrite { refer = document.referrer.split("/"); obj = { rid: "0", day: "3", type: "1", arc_type: "0" }; constructor(html) { super(html); this.script = [ { type: "text/javascript", src: "//s1.hdslb.com/bfs/static/jinkela/long/js/jquery/jquery1.7.2.min.js" }, { type: "text/javascript", src: "//s1.hdslb.com/bfs/seed/jinkela/header/header.js", defer: "defer" }, { type: "text/javascript", src: "//s1.hdslb.com/bfs/cm/st/bundle.js", crossorigin: "" }, { src: "//s1.hdslb.com/bfs/static/jinkela/rank/1.rank.ba58f8684a87651e0e1c576df8f918bfa10c1a90.js", defer: "defer" }, { src: "//s1.hdslb.com/bfs/static/jinkela/rank/rank.ba58f8684a87651e0e1c576df8f918bfa10c1a90.js", defer: "defer" }, { type: "text/javascript", src: "//static.hdslb.com/common/js/footer.js", defer: "defer" } ]; API.path.name = "ranking"; this.getIniState(); this.onload = () => { this.afterFlush(); }; } async getIniState() { const json = await xhr({ url: Format.objUrl("https://api.bilibili.com/x/web-interface/ranking", this.obj), responseType: "json", credentials: true }); const data = API.jsonCheck(json); const result = { loading: false, rankRouteParams: { arc_type: 0, day: 3, rankTab: "all", rid: Number(this.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 }] }; result.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 }]; result.rankList = data.data.list; result.note = data.data.note; window.__INITIAL_STATE__ = result; this.flushDocument(); API.addCss("@media screen and (min-width: 1400px){.main-inner {width: 1160px !important;}}"); } afterFlush() { } } new Ranking("ranking.html"); //# sourceURL=API://@Bilibili-Old/url/ranking.js`; /*!***********************!*/ /**/modules["read.js"] = /*** ./dist/url/read.js ***/ `class Read extends API.rewrite { data; temp = ''; bar = [ [0, "推荐", "home"], [2, "动画", "douga"], [1, "游戏", "game"], [28, "影视", "cinephile"], [3, "生活", "life"], [29, "兴趣", "interest"], [16, "轻小说", "lightnovel"], [17, "科技", "technology"], [41, "笔记", "note"] ]; constructor(html) { super(html); this.script = [ { src: "//static.hdslb.com/public/intersection-observer.js" }, { src: "//static.hdslb.com/public/timing.min.js" }, { src: "//static.hdslb.com/js/jquery-3.3.1.min.js" }, { type: "text/javascript", charset: "utf-8", src: "//s1.hdslb.com/bfs/seed/jinkela/header/header.js" }, { type: "text/javascript", charset: "utf-8", src: "//static.hdslb.com/common/js/footer.js" }, { type: "text/javascript", src: "//static.hdslb.com/phoenix/dist/js/comment.min.js" }, { src: "//s1.hdslb.com/bfs/static/biliapp/biliapp.js" }, { type: "text/javascript", src: "//s1.hdslb.com/bfs/static/jinkela/article/manifest.e5d43b1ea4f5a12408d8cd222049b34cfacd107c.js" }, { type: "text/javascript", src: "//s1.hdslb.com/bfs/static/jinkela/article/vendor.e5d43b1ea4f5a12408d8cd222049b34cfacd107c.js" }, { type: "text/javascript", src: "//s1.hdslb.com/bfs/static/jinkela/article/pcDetail.e5d43b1ea4f5a12408d8cd222049b34cfacd107c.js" } ]; API.path.name = "read"; this.getIniState(); } async getIniState() { const data = await xhr({ url: location.href, credentials: true }); this.data = data.includes("__INITIAL_STATE__=") ? JSON.parse(data.match(/INITIAL_STATE__=.+?\\;\\(function/)[0].replace(/INITIAL_STATE__=/, "").replace(/;\\(function/, "")) : ""; if (!this.data) toast.error("获取专栏数据失败!"); this.bars(); } bars() { this.temp += this.bar.reduce((o, d) => { o = o + \`\${d[1]}\`; return o; }, \`"; this.upinfo(); } upinfo() { this.temp += \`\`; this.head(); } head() { this.temp += \`\`; this.body(); } body() { this.temp += \`
          \${this.data.readInfo.content}

          本文为我原创

          \`; this.tag(); } tag() { this.temp += (this.data.readInfo.tags || []).reduce((o, d) => { o = o + \`
        • \${d.name}
        • \`; return o; }, \`
            \`) + \`
          -- --
          • 投诉或建议
          评论
          \`; this.origin(); } origin() { window.original = { cvid: this.data.cvid, author: { name: this.data.readInfo.author.name, mid: this.data.readInfo.author.mid, }, banner_url: this.data.readInfo.banner_url || (this.data.readInfo && this.data.readInfo.image_urls[0]) || null, reprint: this.data.readInfo.reprint, summary: this.data.readInfo.summary, media: "", actId: this.data.readInfo.act_id, dispute: { dispute: "", dispute_url: "" }, spoiler: "0" }; document.querySelector(".page-container").innerHTML = this.temp; this.flushDocument(); API.runWhile(() => document.body, () => API.importModule("user-select.js")); } } new Read("read.html"); //# sourceURL=API://@Bilibili-Old/url/read.js`; /*!***********************!*/ /**/modules["watchlater.js"] = /*** ./dist/url/watchlater.js ***/ `class Watchlater extends API.rewrite { constructor(html) { super(html); this.script = [ { type: "text/javascript", src: "//static.hdslb.com/js/jquery.min.js" }, { type: "text/javascript", src: "//static.hdslb.com/js/jquery.qrcode.min.js" }, { type: "text/javascript", src: "//s1.hdslb.com/bfs/seed/jinkela/header/header.js" }, { type: "text/javascript", src: "//static.hdslb.com/common/js/footer.js" }, { type: "text/javascript", src: "//static.hdslb.com/js/swfobject.js" }, { type: "text/javascript", src: "//static.hdslb.com/account/bili_quick_login.js" }, { type: "text/javascript", src: "//static.hdslb.com/phoenix/dist/js/comment.min.js" }, { type: "text/javascript", src: "//static.hdslb.com/mstation/js/upload/moxie.js" }, { type: "text/javascript", src: "//static.hdslb.com/mstation/js/upload/plupload.js" }, { type: "text/javascript", src: "//static.hdslb.com/elec_2/dist/js/later_elec.js" }, { type: "text/javascript", src: "//s1.hdslb.com/bfs/static/phoenix/viewlater/static/js/main.2111469a1bbc20e2e885.js" } ]; API.path.name = "watchlater"; this.mediaSession(); this.flushDocument(); this.onload = () => { this.afterFlush(); }; } mediaSession() { API.jsonphook("api.bilibili.com/x/v2/history/toview/web", undefined, obj => { API.switchVideo(async () => { const data = obj.data.list.find(d => d.aid == API.aid); data && API.mediaSession({ title: data.pages.find(d => d.cid == API.cid).part || data.title, artist: data.owner.name, album: data.title, artwork: [{ src: data.pic }] }); }); return obj; }); } afterFlush() { window.commentAgent = { seek: (t) => window.player && window.player.seek(t) }; // 修复评论跳转 config.enlike && API.importModule("enLike.js"); // 添加点赞功能 API.addCss(API.getModule("mini-bofqi.css")); // 修正迷你播放器样式 API.importModule("videoSort.js"); // 修正分区信息 API.path.forEach(d => { d.includes("av") && (API.aid = Number(/[0-9]+/.exec(d)[0])); }); } } if (API.path[5] && API.path[5].startsWith("watchlater") && config.watchlater) location.replace("https://www.bilibili.com/watchlater/#/"); new Watchlater("watchlater.html"); //# sourceURL=API://@Bilibili-Old/url/watchlater.js`; /*!***********************!*/ /**/modules["av.js"] = /*** ./dist/url/av/av.js ***/ `class Av extends API.rewrite { constructor(html) { super(html); this.script = [ { type: "text/javascript", src: "//static.hdslb.com/js/jquery.min.js" }, { type: "text/javascript", src: "//s1.hdslb.com/bfs/seed/jinkela/header/header.js" }, { type: "text/javascript", text: \`window.getInternetExplorerVersion=function(){var rv=-1;if(navigator.appName=="Microsoft Internet Explorer"){var ua=navigator.userAgent;var re=new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})");if(re.exec(ua)!=null){rv=parseFloat(RegExp.\$1)}}return rv};function getQueryString(name){var reg=new RegExp("(^|&)"+name+"=([^&]*)(&|\$)");var r=window.location.search.substr(1).match(reg);if(r!=null){return unescape(r[2])}return null}\` }, { src: "//s1.hdslb.com/bfs/static/jinkela/videoplay/manifest.b1b7706abd590dd295794f540f7669a5d8d978b3.js", crossorigin: "", defer: "defer" }, { src: "//s1.hdslb.com/bfs/static/jinkela/videoplay/vendor.b1b7706abd590dd295794f540f7669a5d8d978b3.js", crossorigin: "", defer: "defer" }, { src: "//s1.hdslb.com/bfs/static/jinkela/videoplay/video.b1b7706abd590dd295794f540f7669a5d8d978b3.js", crossorigin: "", defer: "defer" }, { type: "text/javascript", text: \`var vd=window.__INITIAL_STATE__&&window.__INITIAL_STATE__.videoData;if(vd&&vd.aid&&getInternetExplorerVersion()!==9){\$("#__bofqi").innerHTML='
          ';if(vd.embedPlayer){var p=getQueryString("p")?getQueryString("p")-1:0;var player={aid:vd.aid,cid:(vd.pages[p]&&vd.pages[p].cid)||vd.pages[0].cid};EmbedPlayer("player","//static.hdslb.com/play.swf","cid="+player.cid+"&aid="+player.aid+"&pre_ad=")}if(vd.embed){\$("#bofqi").html(vd.embed)}}else{\$("#bofqi").remove()};\`, defer: "defer" }, { type: "text/javascript", src: "//static.hdslb.com/phoenix/dist/js/comment.min.js" }, { type: "text/javascript", src: "//static.hdslb.com/js/jquery.qrcode.min.js" }, { type: "text/javascript", charset: "utf-8", src: "//static.hdslb.com/common/js/footer.js" } ]; this.getIniState(); this.onload = () => { this.afterFlush(); }; API.importModule("hookWebpackJsonp.js"); // 修复原生代码错误 } async getIniState() { if (API.path[4].toLowerCase().startsWith('bv')) API.aid = API.abv(API.path[4].split("#")[0].split("?")[0]); API.aid = API.aid || Number(/[0-9]+/.exec(String(API.path[4]))[0]); API.path.name = "av"; await new Promise(r => { xhr({ url: Format.objUrl("https://api.bilibili.com/x/web-interface/view/detail", { aid: API.aid }), responseType: "json", credentials: true }).then(d => { this.__INITIAL_STATE__ = new API.initialStateOfAv(d).detail(); this.appendIniState(); r(true); }).catch(e => { toast.error(\`获取av号信息失败,尝试访问第三方接口~\`, e); xhr({ url: Format.objUrl("https://www.biliplus.com/api/view", { id: API.aid }), responseType: "json" }).then(d => { this.__INITIAL_STATE__ = new API.initialStateOfAv(d).plus(); this.appendIniState(); r(true); }).catch(e => { toast.error(\`第三方接口也没有获取到有效数据~\`, e); new API.url().getJson("api.bilibili.com/view", { id: API.aid, page: this.url.searchParams.get("p") }).then(d => { this.__INITIAL_STATE__ = new API.initialStateOfAv(d).view(); this.appendIniState(); API.switchVideo(() => { toast.warning("这可能是个Bangumi,可惜未能获取到ssid,无法跳转~"); }); r(true); }).catch(e => { toast.error(\`上古接口还是没能获取到有效数据~\`); throw e; }); }); }); }); if (this.__INITIAL_STATE__.videoData.redirect_url) return toast.warning("番剧重定向...", this.__INITIAL_STATE__.videoData.redirect_url); if (this.__INITIAL_STATE__.videoData.stein_guide_cid) this.stop("这似乎是个互动视频!抱歉!旧版播放器无法支持 ಥ_ಥ"); API.aid = this.__INITIAL_STATE__.aid; API.tid = this.__INITIAL_STATE__.videoData.tid; API.like = this.__INITIAL_STATE__.stat?.like; API.switchVideo(() => { API.mediaSession({ title: this.__INITIAL_STATE__.videoData.pages.find(t => t.cid == API.cid).part || this.__INITIAL_STATE__.videoData.title, artist: this.__INITIAL_STATE__.videoData.owner.name, album: this.__INITIAL_STATE__.videoData.title, artwork: [{ src: this.__INITIAL_STATE__.videoData.pic }] }); }); this.flushDocument(); } appendIniState() { this.script.unshift({ type: "text/javascript", text: \`window.__INITIAL_STATE__=\${JSON.stringify(this.__INITIAL_STATE__)};(function(){var s;(s=document.currentScript||document.scripts[document.scripts.length-1]).parentNode.removeChild(s);}());\` }); } afterFlush() { API.runWhile(() => document.getElementsByClassName("bili-header-m")[1], () => document.getElementsByClassName("bili-header-m")[1].remove()); // 移除上古顶栏 window.commentAgent = { seek: (t) => window.player && window.player.seek(t) }; // 修复评论跳转 config.enlike && API.importModule("enLike.js"); // 添加点赞功能 config.upList && this.__INITIAL_STATE__.videoData.staff && API.importModule("upList.js", { staff: this.__INITIAL_STATE__.videoData.staff }); // 合作UP主 API.importModule("descBV.js"); // 修复简介中超链接 config.commandDm && API.importModule("commandDm.js"); // 互动弹幕 API.importModule("videoSort.js"); // 修正分区信息 config.electric && API.jsonphook("api.bilibili.com/x/web-interface/elec/show", url => Format.objUrl(url, { aid: 1, mid: 1 })); /dmid/.test(location.href) && /dm_progress/.test(location.href) && API.importModule("loadByDmid.js"); } } if (/\\/s\\//.test(location.href)) location.replace(location.href.replace("s/video", "video")); new Av("av.html"); //# sourceURL=API://@Bilibili-Old/url/av/av.js`; /*!***********************!*/ /**/modules["collection.js"] = /*** ./dist/url/av/collection.js ***/ `{ function calcDivWidth(text) { let elem = document.createElement("div"); elem.setAttribute("style", "display: inline-block"); elem.innerText = text; document.body.append(elem); let w = elem.clientWidth; document.body.removeChild(elem); return w; } function calcOffsetPos(elem) { let result = { x: 0, y: 0 }; for (let e = elem; e != null; e = e.offsetParent) { result.x += e.offsetLeft; result.y += e.offsetTop; } return result; } function getAid() { return window.history.state?.aid; } class CollectionElement { container; clearfix; items = []; spread = null; constructor(onSpread) { this.container = document.createElement("div"); this.clearfix = document.createElement("ul"); this.clearfix.className = "clearfix"; this.container.appendChild(this.clearfix); if (onSpread) { this.spread = document.createElement("a"); this.spread.className = "item v-part-toggle"; this.spread.addEventListener("click", (e) => { onSpread(); e.preventDefault(); }); this.clearfix.appendChild(this.spread); } } setContainerAttr(attr) { let staticClass = "multi-page bili-wrapper report-wrap-module report-scroll-module"; this.container.className = [staticClass, attr.class].join(' ').trim(); } setItemAttrs(attrs) { // 更新分集DOM节点数量 while (this.items.length > attrs.length) this.clearfix.removeChild(this.items.pop().node); while (this.items.length < attrs.length) { let i = { click: null, node: document.createElement("a") }; i.node.addEventListener("mouseenter", (e) => this.showFloatTxt(e)); i.node.addEventListener("mouseleave", () => this.hideFloatText()); i.node.addEventListener("click", (e) => { // 参考vue router-link中防跳转处理 if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey || e.defaultPrevented || e.button != 0) return; e.preventDefault(); i.click && i.click(e); }); this.clearfix.insertBefore(i.node, this.spread); this.items.push(i); } // 更新DOM节点属性 const staticClass = "item"; for (let i = 0; i < this.items.length; i++) { this.items[i].node.className = [staticClass, attrs[i].class].join(' ').trim(); this.items[i].node.innerText = attrs[i].text; this.items[i].node.href = attrs[i].href; this.items[i].click = attrs[i].click; } } setSpreadAttr(attr) { if (this.spread) { this.spread.style.top = attr.top + "px"; attr.text && (this.spread.innerText = attr.text); } } showFloatTxt(e) { let item = e.target; let treshold = calcDivWidth(item.innerText) + 14; if (item.offsetWidth >= treshold) return; let floatTxt = document.createElement("div"); floatTxt.className = "p-float-txt"; floatTxt.innerText = item.innerText; document.body.appendChild(floatTxt); let pos = calcOffsetPos(item); floatTxt.style.left = pos.x + 'px'; floatTxt.style.top = pos.y - 8 - floatTxt.clientHeight + 'px'; // transition代替animate() floatTxt.style.transition = "opacity 0.4s, top 0.4s cubic-bezier(0.37, 0, 0.63, 1)"; floatTxt.style.top = pos.y - 3 - floatTxt.clientHeight + 'px'; floatTxt.style.opacity = "1"; } hideFloatText() { let e = document.querySelector(".p-float-txt"); e && document.body.removeChild(e); } } class CollectionData { notify = null; _viewEpisodes = []; _ep = 0; _spread = false; _spreadBtnTop = 0; _colCount = 4; episodes = []; get viewEpisodes() { return this._viewEpisodes; } get ep() { if (this.episodes[this._ep].aid != getAid()) this._ep = this.episodes.findIndex((ep) => ep.aid == getAid()); return this._ep; } get spreadBtnTop() { return this._spreadBtnTop; } set spreadBtnTop(n) { if (this._spreadBtnTop != n) { this._spreadBtnTop = n; this.notify?.spreadBtnTop(this._spreadBtnTop); } } get spread() { return this._spread; } get colCount() { return this._colCount; } constructor(season) { this.initEpisodes(season); this.calcColCount(); this._viewEpisodes = !this.needSpread() ? this.episodes : this.calcViewEpisodesOnCollapsed(this.ep); } initEpisodes(season) { season.sections.forEach((section) => { Array.prototype.push.apply(this.episodes, section.episodes); }); } calcColCount() { let w = calcDivWidth(this.episodes[this.ep].title); this._colCount = w >= 241 ? 3 : w >= 186 ? 4 : w >= 149 ? 5 : w >= 123 ? 6 : window.innerWidth > 1440 ? 7 : 6; } calcViewEpisodesOnCollapsed(ep) { let begin = ep == 0 ? 0 : ep - 1 + this._colCount <= this.episodes.length ? ep - 1 : this.episodes.length - this._colCount; return this.episodes.slice(begin, begin + this._colCount); } needSpread() { return this._colCount < this.episodes.length || this.spread; } toggleSpread() { this._spread = !this._spread; this._viewEpisodes = this._spread ? this.episodes : this.calcViewEpisodesOnCollapsed(this.ep); this._spreadBtnTop = 0; this.calcColCount(); this.notify?.spread(this._spread); } updateEp() { let ep = this._ep; if (ep == this.ep) return; this._viewEpisodes = this._spread ? this.episodes : this.calcViewEpisodesOnCollapsed(this.ep); this.notify?.ep(); } } class CollectionComponent { data; elem; constructor(season, player) { this.data = new CollectionData(season); this.elem = new CollectionElement(this.data.needSpread() ? () => this.data.toggleSpread() : null); // 替换播放器换P处理 window.callAppointPart = (_p, video) => { let state = { aid: video.aid, cid: video.cid }; window.history.pushState(state, null, "/video/av" + video.aid); this.onRouteChanged(state); }; window.addEventListener("popstate", (e) => { this.reloadPlayer(e.state); this.onRouteChanged(e.state); }); window.addEventListener("scroll", () => this.onWindowScroll()); this.render(); player.parentNode.insertBefore(this.elem.container, player); this.data.notify = { spread: (spread) => { this.render(); // 收起时页面滚动 !spread && window.scroll({ top: calcOffsetPos(document.getElementById("viewbox_report")).y }); }, spreadBtnTop: (top) => { this.elem.setSpreadAttr({ top: top }); }, ep: () => this.render() }; } render() { this.elem.setContainerAttr({ class: "col-" + this.data.colCount }); this.elem.setItemAttrs(this.data.viewEpisodes.map((p) => { return { class: p.aid == getAid() ? "on" : "", href: "/video/av" + p.aid, text: p.title, click: (_e) => { let video = { aid: p.aid, cid: p.cid }; this.reloadPlayer(video); window.callAppointPart(1, video); } }; }, this)); this.elem.setSpreadAttr({ top: this.data.spreadBtnTop, text: this.data.spread ? "收起" : "展开" }); } reloadPlayer(v) { //TODO: 写入播放列表信息 window.GrayManager.reload(\`aid=\${v.aid}&cid=\${v.cid}&has_next=1\`); } onWindowScroll() { if (!this.data.spread) return; // 展开按钮随页面滚动浮动 let div = this.elem.container; let btn = this.elem.spread; let divY = calcOffsetPos(div).y; let maxTop = div.clientHeight - btn.clientHeight - 20; this.data.spreadBtnTop = window.scrollY <= divY - 20 ? 0 : Math.min(window.scrollY - divY + 20, maxTop); } onRouteChanged(state) { this.data.updateEp(); // 视频信息刷新 let avComponent = window.biliUIcomponents; // 评论和标签通过修改组件aid刷新 avComponent.\$store.state.aid = state.aid; // 简介, 标题, 视频统计 xhr({ url: Format.objUrl("https://api.bilibili.com/x/web-interface/view/detail", { aid: state.aid }), responseType: "json", credentials: true }).then((d) => { avComponent?.setVideoData(d.data?.View); }); // 下方视频推荐 xhr({ url: Format.objUrl("https://api.bilibili.com/x/web-interface/archive/related", { aid: state.aid }), responseType: "json", credentials: true }).then((d) => avComponent.related = d.data); // 收藏/投币状态 avComponent.initPage(); //TODO: 分区修复 & 点赞数 } } class Collection { component; constructor(videoData) { API.runWhile(() => document.getElementById("__bofqi"), () => { try { let player = document.getElementById("__bofqi"); window.history.replaceState({ aid: videoData.aid, cid: videoData.cid }, null); this.component = new CollectionComponent(videoData.ugc_season, player); this.component.render(); } catch (e) { toast.error("collection.js", e); } }); } static needDisplay(videoData) { return videoData.videos <= 1 && videoData.ugc_season && videoData.is_season_display; } static run(videoData) { this.needDisplay(videoData) && new Collection(videoData); } } //@ts-ignore Collection.run(videoData); } //# sourceURL=API://@Bilibili-Old/url/av/collection.js`; /*!***********************!*/ /**/modules["commandDm.js"] = /*** ./dist/url/av/commandDm.js ***/ `{ API.addCss(API.getModule("commandDm.css")); let player, widgetContainer; let playing = false; let visible = true; let commandDm = { visible: [], hidden: [] // 未显示的互动弹幕 }; /** * 初始化互动弹幕功能 */ function init(cdm) { if (window.player) { if (widgetContainer === undefined) widgetContainer = initContainer(); player = window.player; bindEvents(); load(cdm); } else throw "获取window.player失败"; } /** * 添加互动弹幕 * @param commandDmRaw 从服务器获得的互动弹幕数据 */ function load(commandDmRaw) { commandDm.hidden = parseDm(commandDmRaw); resize(); } /** * 创建互动弹幕的容器div * @returns div.bilibili-player-video-popup */ function initContainer() { let videoWrap = document.getElementsByClassName("bilibili-player-video-wrap")[0]; if (!videoWrap) throw "未能获取播放器div"; let widgetContainer = document.createElement("div"); widgetContainer.className = "bilibili-player-video-popup"; videoWrap.appendChild(widgetContainer); return widgetContainer; } /** * 绑定播放器事件,使用window.player.addEventListener */ function bindEvents() { const EVENT = { VIDEO_MEDIA_PLAYING: "video_media_playing", VIDEO_MEDIA_PAUSE: "video_media_pause", VIDEO_MEDIA_SEEK: "video_media_seek", VIDEO_MEDIA_SEEKED: "video_media_seeked", VIDEO_MEDIA_ENDED: "video_media_ended", VIDEO_RESIZE: "video_resize", VIDEO_PLAYER_RESIZE: "video_player_resize", VIDEO_DESTROY: "video_destroy" }; player.addEventListener(EVENT.VIDEO_MEDIA_PLAYING, play); player.addEventListener(EVENT.VIDEO_MEDIA_PAUSE, pause); player.addEventListener(EVENT.VIDEO_MEDIA_SEEK, pause); player.addEventListener(EVENT.VIDEO_MEDIA_SEEKED, play); player.addEventListener(EVENT.VIDEO_MEDIA_ENDED, pause); player.addEventListener(EVENT.VIDEO_PLAYER_RESIZE, resize); player.addEventListener(EVENT.VIDEO_DESTROY, destroy); // 开启/关闭弹幕事件 document.querySelector("div.bilibili-player-video-control > div.bilibili-player-video-btn.bilibili-player-video-btn-danmaku").addEventListener("click", (event) => { let option = event.target.getAttribute("name"); if (option == "ctlbar_danmuku_close") { visible = false; pause(); widgetContainer.style.display = "none"; } else if (option == "ctlbar_danmuku_on") { visible = true; play(); widgetContainer.style.display = ""; } }); } /** * 生成互动弹幕的UI组件,各种后续处理 * @param commandDmRaw 互动弹幕原始数据 * @returns 互动弹窗的UI对象 */ function parseDm(commandDmRaw) { let popupWindow = []; for (let i = 0, cdm, extra, from; i < commandDmRaw.length; i++) { cdm = commandDmRaw[i]; extra = JSON.parse(cdm.extra); from = cdm.progress / 1000; switch (cdm.command) { // 4种将会弹出界面的互动弹幕(见原生代码appendPopup()) case "#ATTENTION#": case "#ACTORFOLLOW#": case "#MANAGERFOLLOW#": debug.warn("未被支持的互动弹幕类型:" + cdm.command); debug.warn(cdm); break; case "#VOTE#": // 投票弹窗 popupWindow.push(new Vote(cdm, extra, from)); break; case "#GRADE#": // 评分弹窗 popupWindow.push(new Grade(cdm, extra, from)); break; // 滚动弹幕(见原生代码appendDmImg()),它们的渲染也许需要去修改原生弹幕渲染器 case "#LINK#": popupWindow.push(new Link(cdm, extra, from)); break; case "#RESERVE#": case "#ACTOR#": case "#ACTIVITYCOMBO#": debug.warn("未被支持的互动弹幕类型:" + cdm.command); debug.warn(cdm); break; } } return popupWindow; } function play() { if (visible) { playing = true; loop(); } } function pause() { playing = false; loop(); } /** * 播放器大小更改时触发 */ function resize() { // 获得当前播放器显示分辨率与最小分辨率(680x504)时的缩放比,用于UI缩放 let scaleX = widgetContainer.clientWidth / 680; let scaleY = widgetContainer.clientHeight / 504; for (let i = 0; i < commandDm.visible.length; i++) { commandDm.visible[i].resize(scaleX, scaleY, widgetContainer.clientWidth, widgetContainer.clientHeight); } for (let i = 0; i < commandDm.hidden.length; i++) { commandDm.hidden[i].resize(scaleX, scaleY, widgetContainer.clientWidth, widgetContainer.clientHeight); } } function loop() { let time = player.getCurrentTime(); // 获得以秒为单位的当前播放进度 if (playing) { requestAnimationFrame(loop); } // 根据播放进度,显示、隐藏互动弹幕界面 for (let i = 0, cdm; i < commandDm.hidden.length; i++) { cdm = commandDm.hidden[i]; if (cdm.from < time && cdm.to > time) { commandDm.visible.push(cdm); commandDm.hidden.splice(i, 1); cdm.show(); resize(); } } for (let i = 0, cdm; i < commandDm.visible.length; i++) { cdm = commandDm.visible[i]; if (cdm.to < time || cdm.from > time) { commandDm.hidden.push(cdm); commandDm.visible.splice(i, 1); cdm.hide(); } } } function destroy() { playing = false; for (let i = 0; i < commandDm.visible.length; i++) { commandDm.visible[i].destroy(); } for (let i = 0; i < commandDm.hidden.length; i++) { commandDm.hidden[i].destroy(); } commandDm.visible.splice(0, commandDm.visible.length); commandDm.hidden.splice(0, commandDm.hidden.length); } function divClass(className) { let div = document.createElement("div"); div.className = className; return div; } function isLoggedin() { if (API.uid) return true; player.pause(); API.bofqiMessage("请先登录"); API.biliQuickLogin(); } function post(url, data, contentType = "application/x-www-form-urlencoded;charset=UTF-8") { data.csrf = API.getCookies().bili_jct; return xhr({ url: url, data: Format.objUrl("", data), headers: { "Content-Type": contentType }, method: "POST", credentials: true }); } /** * 弹窗组件 */ class PopupWindow { popup; duration; from; to; pos_x; pos_y; constructor(cdm, extra, from) { this.duration = extra.duration / 1e3 || 5; this.from = from || 0; this.to = from + (extra.duration / 1e3 || 5); this.pos_x = extra.posX || 200; this.pos_y = extra.posY || 200; this.popup = divClass("commandDm-popup"); this.popup.style.display = "none"; widgetContainer.appendChild(this.popup); } show() { this.popup.style.display = ""; requestAnimationFrame(() => this.popup.className = "commandDm-popup on"); } hide() { this.popup.className = "commandDm-popup"; setTimeout(() => this.popup.style.display = "none", 200); } destroy() { } /** * 根据视频区域大小等比缩放投票界面 */ resize(scaleX, scaleY, containerWidth, containerHeight) { this.popup.style.transform = "translateX(-50%) translateY(-50%) scale(" + Math.min((scaleX + scaleY) / 2, 1.5) + ")"; let left = this.pos_x * scaleX; let top = this.pos_y * scaleY; left = Math.max(left, this.popup.clientWidth / 2); top = Math.max(top, this.popup.clientHeight / 2); left = Math.min(left, containerWidth - this.popup.clientWidth / 2); top = Math.min(top, containerHeight - this.popup.clientHeight / 2); this.popup.style.left = left + "px"; this.popup.style.top = top + "px"; } } /** * 投票互动UI */ class Vote extends PopupWindow { total; voteId; options; question; myVote; dialog; result; button; count; progress; constructor(cdm, extra, from) { super(cdm, extra, from); this.popup.style.width = "150px"; this.total = extra.cnt; this.voteId = extra.vote_id; this.options = extra.options; this.question = extra.question; this.myVote = extra.my_vote; // 0:未投票 非零数字:已投票,my_vote的值即为已投项的idx let dialog = divClass("vote-dialog"); let panel = divClass("vote-panel"); let title = divClass("vote-title"); title.innerHTML = this.question; let optionDiv = divClass("vote-option"); let button = []; for (let i = 0, btn, opt; i < this.options.length; i++) { // 投票按钮 opt = this.options[i]; btn = divClass("vote-button"); btn.innerHTML = opt.desc; btn.setAttribute("idx", opt.idx); btn.onclick = () => this.goVote(opt.idx, i); button[i] = btn; optionDiv.appendChild(btn); } panel.appendChild(optionDiv); dialog.appendChild(title); dialog.appendChild(panel); this.popup.appendChild(dialog); this.dialog = dialog; this.button = button; this.progress = []; // 已投票则直接显示结果 if (this.myVote !== 0) { this.showResult(); this.progress[this.myVote - 1].className = "vote-progress vote-progress-blue"; } ; } goVote(idx, i) { if (isLoggedin()) { this.total += 1; this.options[i].cnt += 1; // 发送投票操作到服务器 let url = "//api.bilibili.com/x/web-interface/view/dm/vote"; post(url, { aid: API.aid, cid: API.cid, progress: Math.max(Math.round(1e3 * player.getCurrentTime()), 1), vote: idx, vote_id: this.voteId }).then((resp) => { resp = JSON.parse(resp); biliAPI.verify(resp, "投票"); this.progress[i].className = "vote-progress vote-progress-blue"; }); this.myVote = idx; this.showResult(); this.to += 5; //点击投票后推迟5秒消失,防止结果消失太快来不及看 } } showResult() { // 显示票数、比例条 this.count = []; for (let i = 0, progress, desc; i < this.button.length; i++) { this.button[i].onclick = null; this.button[i].innerHTML = ""; this.button[i].className = "vote-progress-bg"; progress = divClass("vote-progress"); desc = divClass("vote-progress-desc"); desc.innerHTML = this.options[i].desc; progress.appendChild(desc); this.button[i].appendChild(progress); this.progress[i] = progress; // 结果数据 let cnt = divClass("vote-count"); cnt.innerHTML = this.options[i].cnt; this.count[i] = cnt; this.button[i].appendChild(cnt); } this.resultAnimation(); } /** * 投票结果的动画 */ resultAnimation() { // 投票比例条型图向右展开 for (let i = 0; i < this.progress.length; i++) { this.progress[i].style.width = "0"; requestAnimationFrame(() => this.progress[i].style.width = (this.options[i].cnt / this.total * 100) + "%"); } // 右侧票数递增动画,持续0.8秒 let start = performance.now(); let frame = (t) => { let percentage = (t - start) * 0.00125; if (percentage < 1) requestAnimationFrame(frame); else percentage = 1; for (let i = 0; i < this.count.length; i++) { this.count[i].innerHTML = Math.floor(this.options[i].cnt * percentage); } }; requestAnimationFrame(frame); } show() { super.show(); if (this.myVote !== 0) { this.resultAnimation(); } } hide() { super.hide(); this.to = this.from + this.duration; // 重设消失时间 } } class Grade extends PopupWindow { /* avg_score: 8.7 <= 平均评分 count: 2990 duration: 5000 grade_id: 14369 mid_score: 0 <= 当前用户的评分 msg: "评分标题" <= 最长为8个汉字 posX: 344 posY: 159 skin_selected: "http://i0.hdslb.com/bfs/b/ee3aca3dbc22087341cf312d71a1354af527e444.png" skin_unselected: "http://i0.hdslb.com/bfs/b/1d8fc3daf9201d70189a3778e605d2acf9cae7e9.png" */ gradeInfo; scoreInfo; scoreButton; constructor(cdm, info, from) { super(cdm, info, from); this.popup.style.width = "184px"; this.gradeInfo = info; this.popup.innerHTML = \`
          \${info.msg}
          \${info.count}人参与 \`; this.scoreInfo = this.popup.getElementsByClassName("grade-score-info")[0]; let scoreArea = this.popup.getElementsByClassName("grade-score-area")[0]; let scoreButton = []; function highlightScores(i) { for (let m = 0; m < 5; m++) { if (m <= i && !scoreButton[m].highlight) { scoreButton[m].highlight = true; scoreButton[m].className = "highlight"; } else if (m > i && scoreButton[m].highlight) { scoreButton[m].highlight = false; scoreButton[m].className = ""; } } } for (let i = 0; i < 5; i++) { let score = document.createElement("div"); scoreButton[i] = score; score.innerHTML = \` \`; scoreArea.appendChild(score); if (info.mid_score === 0) { score.onmouseenter = () => highlightScores(i); score.onclick = () => { if (isLoggedin()) { this.gradeInfo.avg_score = (this.gradeInfo.count * this.gradeInfo.avg_score + (i + 1) * 2) / (this.gradeInfo.count + 1); this.gradeInfo.avg_score = this.gradeInfo.avg_score.toPrecision(2); this.gradeInfo.count += 1; this.popup.getElementsByClassName("grade-avg-score")[0].innerHTML = this.gradeInfo.avg_score; this.popup.getElementsByClassName("grade-score-count")[0].innerHTML = this.gradeInfo.count + "人参与"; this.showResult(); for (let index = 0; index < 5; index++) { if (index <= i) { scoreButton[index].style.animation = "grade-score-hit 0.7s ease forwards"; setTimeout(() => scoreButton[index].style.animation = "", 1000); } scoreButton[index].onclick = null; scoreButton[index].onmouseenter = null; } scoreArea.onmouseleave = null; scoreArea.classList.remove("pointer"); this.goGrade((i + 1) * 2); } }; } } ; if (info.mid_score === 0) scoreArea.onmouseleave = () => highlightScores(-1); this.scoreButton = scoreButton; if (info.mid_score != 0) { this.showResult(); highlightScores(info.mid_score / 2 - 1); scoreArea.classList.remove("pointer"); } } goGrade(score) { post("https://api.bilibili.com/x/v2/dm/command/grade/post", { aid: API.aid, cid: API.cid, progress: parseInt(player.getCurrentTime()) * 1000, grade_id: this.gradeInfo.grade_id, grade_score: score }); this.to += 3; } showResult() { this.scoreInfo.style.display = ""; this.scoreInfo.style.animation = "grade-score-showup 0.3s ease 0.2s forwards"; for (let i = 0; i < 4; i++) { setTimeout(() => this.scoreButton[i].style.width = "24px", i * 50); } } hide() { super.hide(); this.to = this.from + this.duration; } } /** * 用于获取收藏列表有关信息 */ class favList { static list = []; static defaultFolderId = 0; static get() { if (this.list.length > 0) return Promise.resolve(this.list); return xhr({ url: Format.objUrl("//api.bilibili.com/x/v3/fav/folder/created/list-all", { type: String(2), rid: String(API.aid), up_mid: String(API.uid) }), credentials: true }).then((resp) => { resp = JSON.parse(resp); biliAPI.verify(resp, "获取收藏列表"); this.list = resp.data.list; this.list.forEach((v) => v.attr === 1 && (this.defaultFolderId = v.id)); return this.list; }); } static getDefaultFolder() { if (this.defaultFolderId !== 0) return Promise.resolve(this.defaultFolderId); return this.get().then(() => { return this.defaultFolderId; }); } } /** * @see https://github.com/SocialSisterYi/bilibili-API-collect */ class biliAPI { static verify(resp, msg) { if (resp.code !== 0) { toast.error(msg + "失败", resp.code, resp.message); throw msg + "失败"; } return resp; } static like(bool) { bool = bool ? 1 : 2; return post("//api.bilibili.com/x/web-interface/archive/like", { aid: API.aid, like: bool }, "application/json; charset=utf-8").then((resp) => biliAPI.verify(resp, "点赞")); } static follow() { return post("//api.bilibili.com/x/relation/modify", { aid: API.aid, fid: window.getAuthorInfo().mid, act: 1, re_src: 14 }).then((resp) => { resp = JSON.parse(resp); return biliAPI.verify(resp, "关注"); }); } static coin() { } static fav() { return post("//api.bilibili.com/x/v3/fav/resource/deal", { rid: API.aid, type: 2, add_media_ids: favList.defaultFolderId, }).then((resp) => { resp = JSON.parse(resp); return biliAPI.verify(resp, "收藏"); }); } static triple() { return post("//api.bilibili.com/x/web-interface/archive/like/triple", { aid: API.aid }, "application/json; charset=utf-8").then((resp) => { biliAPI.verify(resp, "三连"); let d = resp.data; if (d.coin && d.like && d.fav) return; if (!d.coin) toast.error("投币失败"); if (!d.like) toast.error("点赞失败"); if (!d.fav) toast.error("收藏失败"); return d; }); } } /** * 关联视频跳转按钮 */ class Link { /* extra = { aid: 2 bvid: "BV1xx411c7mD" icon: "http://i0.hdslb.com/bfs/archive/03ef3f34944e0f78b1b4050fc3f9705d1fa905e3.png" posX: 333.5 posY: 93.7 title: "字幕君交流场所" } */ content; aid; from; to; pos_x; pos_y; button; constructor(cdm, extra, from) { this.content = cdm.content; this.aid = extra.aid; this.from = from || 0; this.to = from + 5; this.pos_x = extra.posX || 200; this.pos_y = extra.posY || 200; /* */ let button = divClass("link-button"); let img = document.createElement("img"); img.src = "https://static.hdslb.com/images/favicon.ico"; let span = document.createElement("span"); span.innerHTML = this.content; button.appendChild(img); button.appendChild(span); button.style.display = "none"; button.onclick = () => { player.pause(); window.open("https://www.bilibili.com/video/av" + this.aid); }; widgetContainer.appendChild(button); this.button = button; } show() { this.button.style.display = "block"; } hide() { this.button.style.display = "none"; } /** * 根据视频区域大小缩放,放大倍数限制在最大1.5倍 */ resize(scaleX, scaleY) { this.button.style.left = (this.pos_x * scaleX) + "px"; this.button.style.top = (this.pos_y * scaleY) + "px"; this.button.style.transform = "translateX(-50%) translateY(-50%) scale(" + Math.min(1.5, (scaleX + scaleY) / 2) + ")"; } destroy() { } } /** * 程序入口 * @param cdm 互动弹幕原始数据 * @param aid aid * @param cid cid */ API.loadCommandDm = async (cdm, aid, cid) => { try { if (aid != API.aid || cid != API.cid || (widgetContainer !== undefined && document.getElementById("bilibiliPlayer").contains(widgetContainer))) { // 正在“载入其他视频弹幕”,不必处理互动弹幕 return; } init(cdm); // 由于切P后整个播放器会被销毁重建,每次载入互动弹幕都需要重新绑定事件 } catch (e) { toast.error("commandDm.js", e); } }; } //# sourceURL=API://@Bilibili-Old/url/av/commandDm.js`; /*!***********************!*/ /**/modules["descBV.js"] = /*** ./dist/url/av/descBV.js ***/ `API.switchVideo(() => { try { let desc = document.getElementsByClassName("info"); if (desc[1] && desc[1].parentNode && desc[1].parentNode.id == "v_desc") { let text = desc[1].textContent; text = text.replace(/[bB][vV]1[fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF]{9}/g, (str) => { const av = API.abv(str); return \`av\${av}\`; }).replace(/(av|sm)[0-9]+/gi, (str) => { str = str.toLowerCase(); return \`\${str}\`; }); desc[1].innerHTML = text; } } catch (e) { debug.error("descBV.js", e); } }); //# sourceURL=API://@Bilibili-Old/url/av/descBV.js`; /*!***********************!*/ /**/modules["enLike.js"] = /*** ./dist/url/av/enLike.js ***/ `{ class Like { aid; coin; span; liked = false; number = API.like || 0; constructor() { API.runWhile(() => { this.coin = API.path.name == "watchlater" ? document.querySelector(".u.coin") : document.querySelector("[report-id*=coin]"); return this.coin && API.aid; }, () => this.init()); } init() { API.addCss(API.getModule("vanfont.css"), "vanfont"); this.style(); this.aid = API.aid; this.span = document.createElement("span"); this.span.classList.add("ulike"); this.coin.parentElement.insertBefore(this.span, this.coin); this.changeLiked(); this.span.addEventListener("click", () => this.setLike()); API.switchVideo(() => this.switch()); try { !this.number && xhr({ url: \`https://api.bilibili.com/x/web-interface/view?aid=\${API.aid}\`, credentials: true, responseType: "json" }).then(d => { this.number = API.jsonCheck(d).data.stat.like; this.changeLiked(); }); API.uid && xhr({ url: \`https://api.bilibili.com/x/web-interface/archive/has/like?aid=\${API.aid}\`, credentials: true, responseType: "json" }).then(d => { d = API.jsonCheck(d).data; d === 1 && (this.liked = true, this.changeLiked()); }); } catch (e) { toast.error("点赞出错!", e); } } style() { let style = \`.ulike {cursor: pointer;}.van-icon-videodetails_like{font-size: 25px;vertical-align: middle;margin-right: 6px;transform: translateY(-1px);}\`; switch (API.path.name) { case "bangumi": style += \`.ulike {position: relative;min-width: 110px;float: left;height: 100%;line-height: 18px;font-size: 12px;color: #222;transform: translateY(-2px);}\`; style += \`.van-icon-videodetails_like{margin-left: 25px;}\`; break; case "watchlater": style += \`.video-info-module .number .ulike {margin-right: 5px;}\`; break; default: style += \`.video-info-m .number .ulike {margin-right: 5px;}\`; } API.addCss(style); } setLike() { if (API.uid) { const like = this.liked ? 2 : 1; xhr({ url: "https://api.bilibili.com/x/web-interface/archive/like", method: "POST", data: \`aid=\${API.aid}&like=\${like}&csrf=\${API.getCookies().bili_jct}\`, credentials: true, responseType: "json" }).then(d => { API.jsonCheck(d).ttl; this.liked = !this.liked; this.number = this.liked ? this.number + 1 : this.number - 1; this.changeLiked(); }); } else API.biliQuickLogin(); } changeLiked() { this.span.innerHTML = \`点赞 \${Format.unitFormat(this.number) || "--"}\`; } switch() { if (this.aid != API.aid) { this.aid = API.aid; xhr({ url: \`https://api.bilibili.com/x/web-interface/view?aid=\${API.aid}\`, credentials: true, responseType: "json" }).then(d => { this.number = API.jsonCheck(d).data.stat.like; this.changeLiked(); }); } } } new Like(); } //# sourceURL=API://@Bilibili-Old/url/av/enLike.js`; /*!***********************!*/ /**/modules["hookWebpackJsonp.js"] = /*** ./dist/url/av/hookWebpackJsonp.js ***/ `{ let webpackJsonpFunction; Object.defineProperty(window, "webpackJsonp", { get() { if (webpackJsonpFunction) { return (chunkIds, moreModules, executeModules) => { function inject(index, replaceFn) { let code = moreModules[index].toString(); moreModules[index] = new Function("t", "e", "i", "(" + replaceFn(code) + ")(t,e,i)"); } // length == 716 -> vendor.js // == 717 -> video.b1b7706abd590dd295794f540f7669a5d8d978b3.js if (moreModules.length == 717) { // 暴露UI组件 // .onCoinSuccess(n) 页面变为已投币n枚的状态 // .onFollow() 变为已关注状态 // .favSubmit(bool) 设置收藏状态,参数bool: true -> “已收藏”状态 false -> 未收藏状态 inject(274, (code) => code.replace("init:function(){", "init:function(){window.biliUIcomponents=this;")); // 修复:收藏视频时,在“添加到收藏夹”弹窗中,如果将视频从收藏夹A删除,并同时添加到收藏夹B,点击确定后窗口不消失的问题 /* 报错原因示意: jQuery.when(deferredA,deferredB).done((resultA,resultB) => { let codeA = resultA[0].code; // Cannot read property 'code' of undefined let codeA = resultA.code; // 本应该写成这样 }) */ inject(251, (code) => code.replace("e[0].code", "e.code").replace("i[0].code", "i.code")); } return webpackJsonpFunction(chunkIds, moreModules, executeModules); }; } }, set(func) { webpackJsonpFunction = func; } }); } //# sourceURL=API://@Bilibili-Old/url/av/hookWebpackJsonp.js`; /*!***********************!*/ /**/modules["initialStateOfAv.js"] = /*** ./dist/url/av/initialStateOfAv.js ***/ `class InitialStateOfAv { __INITIAL_STATE__ = { aid: 0, comment: { count: 0, list: [] }, error: {}, isClient: false, p: "", player: "", playurl: "", related: [], tags: [], upData: { face: "https://static.hdslb.com/images/akari.jpg", name: "", mid: 0, DisplayRank: "0", Official: { desc: "", role: 0, title: "", type: -1 }, approve: false, archiveCount: 0, article: 0, attention: 10, attentions: [], birthday: "", description: "", fans: 44616, friend: 10, level_info: { current_exp: 0, current_level: 6, current_min: 0, next_exp: 0 }, nameplate: { condition: "", image: "", image_small: "", level: "", name: "", mid: 0 }, official_verify: { desc: "", type: -1 }, pendant: { expire: 0, image: "", image_enhance: "", image_enhance_frame: "", name: "", pid: 0 }, place: "", rank: 10000, regtime: 0, sex: "保密", sign: "", spacesta: 0, vip: { accessStatus: 0, dueRemark: "", theme_type: 0, vipStatus: 0, vipStatusWarn: "", vipType: 1 } }, videoData: { aid: 0, cid: 0, config: { relates_title: "相关推荐", share_style: 1 }, copyright: 2, ctime: "", desc: "", dimension: { height: 1080, rotate: 0, width: 1920 }, duration: 360, dynamic: "", owner: {}, pages: [{ cid: 0, dimension: { height: 1080, rotate: 0, width: 1920 }, duration: 360, from: "vupload", page: 1, part: "", vid: "", weblink: "" }], pic: "", pubdate: "", redirect_url: undefined, rights: { autoplay: 0, bp: 0, download: 0, elec: 0, hd5: 0, is_cooperation: 0, movie: 0, no_background: 0, no_reprint: 0, pay: 0, ugc_pay: 0, ugc_pay_preview: 0 }, stat: { aid: 0, coin: 0, danmaku: 0, dislike: 0, favorite: 0, his_rank: 0, like: 0, now_rank: 0, reply: 0, share: 0, view: 0 }, state: 0, stein_guide_cid: undefined, tid: 0, title: 0, tname: 0, videos: 1, embedPlayer: 'EmbedPlayer("player", "//static.hdslb.com/play.swf", "cid:0&aid:0&pre_ad:")' } }; data; constructor(data) { this.data = data; } detail() { this.data = API.jsonCheck(this.data).data; if (!this.data.View.cid && this.data.View.forward) { toast.warning("视频撞车了!正在跳转至原视频~"); location.href = \`https://www.bilibili.com/video/av\${this.data.View.forward}\`; } this.__INITIAL_STATE__.aid = this.data.View.aid; this.__INITIAL_STATE__.related = this.data.Related || []; this.__INITIAL_STATE__.tags = this.data.Tags || []; this.__INITIAL_STATE__.upData = this.data.Card.card || {}; this.__INITIAL_STATE__.upData.archiveCount = this.data.Card.archive_count; this.__INITIAL_STATE__.videoData = this.data.View || {}; this.__INITIAL_STATE__.videoData.embedPlayer = \`EmbedPlayer("player", "//static.hdslb.com/play.swf", "cid=\${this.data.View.cid}&aid=\${this.data.View.aid}&pre_ad=")\`; return this.__INITIAL_STATE__; } plus() { this.data = API.jsonCheck(this.data); this.data.v2_app_api && this.data.v2_app_api.redirect_url && (location.href = this.data.v2_app_api.redirect_url); this.data.bangumi && this.data.bangumi.ogv_play_url && (location.href = this.data.bangumi.ogv_play_url); this.__INITIAL_STATE__.aid = this.data.aid || API.aid; this.__INITIAL_STATE__.upData.name = this.data.author; this.__INITIAL_STATE__.upData.mid = this.data.mid; this.__INITIAL_STATE__.videoData.aid = this.data.aid || API.aid; this.__INITIAL_STATE__.videoData.cid = this.data.list[0].cid; this.__INITIAL_STATE__.videoData.ctime = this.data.created; this.__INITIAL_STATE__.videoData.pubdate = this.data.created; this.__INITIAL_STATE__.videoData.desc = this.data.description; this.__INITIAL_STATE__.videoData.pages[0].cid = this.data.list[0].cid; this.__INITIAL_STATE__.videoData.stat.aid = this.data.aid; this.__INITIAL_STATE__.videoData.stat.coin = this.data.coins; this.__INITIAL_STATE__.videoData.stat.danmaku = this.data.video_review; this.__INITIAL_STATE__.videoData.stat.favorite = this.data.favorites; this.__INITIAL_STATE__.videoData.stat.reply = this.data.review; this.__INITIAL_STATE__.videoData.stat.view = this.data.play; this.__INITIAL_STATE__.videoData.tid = this.data.tid; this.__INITIAL_STATE__.videoData.title = this.data.title; this.__INITIAL_STATE__.videoData.tname = this.data.typename; this.data.v2_app_api && (this.__INITIAL_STATE__.tags = this.data.v2_app_api.tag, this.__INITIAL_STATE__.videoData = this.data.v2_app_api); this.__INITIAL_STATE__.videoData.embedPlayer = \`EmbedPlayer("player", "//static.hdslb.com/play.swf", "cid=\${this.data.list[0].cid}&aid=\${this.data.aid}&pre_ad=")\`; API.switchVideo(() => API.bofqiMessage(["视频已失效", "加载弹幕", "缓存信息仅供参考"], 3)); return this.__INITIAL_STATE__; } view() { this.data = API.jsonCheck(this.data); this.__INITIAL_STATE__.aid = API.aid; this.__INITIAL_STATE__.tags = this.data.tag || []; this.__INITIAL_STATE__.upData.name = this.data.author; this.__INITIAL_STATE__.upData.face = this.data.face; this.__INITIAL_STATE__.upData.mid = this.data.mid; this.__INITIAL_STATE__.videoData.aid = API.aid; this.__INITIAL_STATE__.videoData.cid = this.data.cid; this.__INITIAL_STATE__.videoData.ctime = this.data.created; this.__INITIAL_STATE__.videoData.pubdate = this.data.created; this.__INITIAL_STATE__.videoData.desc = this.data.description; this.__INITIAL_STATE__.videoData.pages[0].cid = this.data.cid; this.__INITIAL_STATE__.videoData.stat.aid = API.aid; this.__INITIAL_STATE__.videoData.stat.coin = this.data.coins; this.__INITIAL_STATE__.videoData.stat.danmaku = this.data.video_review; this.__INITIAL_STATE__.videoData.stat.favorite = this.data.favorites; this.__INITIAL_STATE__.videoData.stat.reply = this.data.review; this.__INITIAL_STATE__.videoData.stat.view = this.data.play; this.__INITIAL_STATE__.videoData.tid = this.data.tid; this.__INITIAL_STATE__.videoData.title = this.data.title; this.__INITIAL_STATE__.videoData.tname = this.data.typename; this.__INITIAL_STATE__.videoData.embedPlayer = \`EmbedPlayer("player", "//static.hdslb.com/play.swf", "cid=\${this.data.cid}&aid=\${API.aid}&pre_ad=")\`; return this.__INITIAL_STATE__; } } API.initialStateOfAv = InitialStateOfAv; //# sourceURL=API://@Bilibili-Old/url/av/initialStateOfAv.js`; /*!***********************!*/ /**/modules["loadByDmid.js"] = /*** ./dist/url/av/loadByDmid.js ***/ `{ const dmid = Format.urlObj(location.href).dmid; let progress = Number(Format.urlObj(location.href).dm_progress); let first = 0; API.switchVideo(async () => { if (!window.player?.seek) { await new Promise(r => { API.runWhile(() => window.player?.seek, r); }); } if (first) return; first++; if (progress) return window.player.seek(progress); if (dmid) { progress = await xhr({ url: \`https://api.bilibili.com/x/v2/dm/thumbup/detail?oid=\${API.cid}&dmid=\${dmid}\`, credentials: true }); progress = API.jsonCheck(progress).data.progress; // 检查xhr返回值并转化为json progress && window.player.seek(progress / 1000 - .2); } }); } //# sourceURL=API://@Bilibili-Old/url/av/loadByDmid.js`; /*!***********************!*/ /**/modules["upList.js"] = /*** ./dist/url/av/upList.js ***/ `API.runWhile(() => document.querySelector("#v_upinfo"), () => { try { let fl = 'UP主列表
          '; // @ts-ignore:该变量由主模块传入 fl = staff.reduce((s, d) => { s = s + \`\`; return s; }, fl) + \`
          \`; document.querySelector("#v_upinfo").innerHTML = fl; API.addCss(API.getModule("upList.css")); } catch (e) { toast.error("upList.js", e); } }); //# sourceURL=API://@Bilibili-Old/url/av/upList.js`; /*!***********************!*/ /**/modules["videoSort.js"] = /*** ./dist/url/av/videoSort.js ***/ `API.runWhile(() => document.querySelector(".tm-info") && API.aid, () => { try { const sort = API.getModule("videoSort.json"); if (API.path.name == "av" && API.tid && API.tid in sort) { const nodes = document.querySelector(".tm-info").childNodes; nodes[1].replaceWith(nodes[0].cloneNode(true)); nodes[2].replaceWith(nodes[0].cloneNode(true)); nodes[2].childNodes[1].remove(); nodes[1].childNodes[0].href = sort[sort[API.tid][0]][2]; nodes[1].childNodes[0].text = sort[sort[API.tid][0]][1]; nodes[2].childNodes[0].href = sort[API.tid][2]; nodes[2].childNodes[0].text = sort[API.tid][1]; } else if (API.path.name == "watchlater") { const nodes = document.querySelector(".tm-info").childNodes; if (nodes[2].nodeType === 8) { xhr({ url: \`https://api.bilibili.com/x/web-interface/view?aid=\${API.aid}\`, responseType: "json" }).then(d => { API.tid = API.jsonCheck(d).data.tid; if (API.tid && API.tid in sort) { nodes[2].replaceWith(nodes[0].cloneNode(true)); nodes[4].replaceWith(nodes[0].cloneNode(true)); nodes[4].childNodes[1].remove(); nodes[2].childNodes[0].href = sort[sort[API.tid][0]][2]; nodes[2].childNodes[0].text = sort[sort[API.tid][0]][1]; nodes[4].childNodes[0].href = sort[API.tid][2]; nodes[4].childNodes[0].text = sort[API.tid][1]; } }); } } } catch (e) { debug.error("videoSort.js", e); } }); //# sourceURL=API://@Bilibili-Old/url/av/videoSort.js`; /*!***********************!*/ /**/modules["bangumi.js"] = /*** ./dist/url/bangumi/bangumi.js ***/ `class Bangumi extends API.rewrite { epid = API.path[5].startsWith('ep') ? Number(location.href.match(/[0-9]+/)[0]) : null; obj = {}; constructor(html) { super(html); this.script = [ { type: "text/javascript", src: "//static.hdslb.com/js/jquery.min.js" }, { type: "text/javascript", src: "//static.hdslb.com/vip/dist/js/vipPlugin.v2.js" }, { type: "text/javascript", src: "//static.hdslb.com/js/promise.auto.min.js" }, { type: "text/javascript", src: "//s1.hdslb.com/bfs/seed/jinkela/header/header.js" }, { src: "//s1.hdslb.com/bfs/static/bangumi/play/1.bangumi-play.809bd6f6d1fba866255d2e6c5dc06dabba9ce8b4.js", crossorigin: "", defer: "defer" }, { src: "//s1.hdslb.com/bfs/static/bangumi/play/bangumi-play.809bd6f6d1fba866255d2e6c5dc06dabba9ce8b4.js", crossorigin: "", defer: "defer" }, { type: "text/javascript", src: "//static.hdslb.com/phoenix/dist/js/comment.min.js" }, { type: "text/javascript", src: "//static.hdslb.com/common/js/footer.js" }, { src: "//s1.hdslb.com/bfs/static/plugin/vip/BilAccountThaw.js" } ]; this.getIniState(); this.onload = () => { this.afterFlush(); }; } async getIniState() { API.path.name = "bangumi"; API.pgc = true; API.path[5].startsWith('ss') && (this.obj.season_id = location.href.match(/[0-9]+/)[0]); API.path[5].startsWith('ep') && (this.obj.ep_id = location.href.match(/[0-9]+/)[0]); if (API.uid && !this.epid) { const data = await xhr({ url: location.href }); const arr = data.match(/last_ep_id\\"\\:[0-9]+/) || []; this.epid = (arr[0] && arr[0].split(":")[1]) || null; } await new Promise(r => { if (this.obj.season_id || this.obj.ep_id) { xhr({ url: Format.objUrl("https://bangumi.bilibili.com/view/web_api/season", this.obj), responseType: "json", credentials: true }).then(d => { this.__INITIAL_STATE__ = new API.initialStateOfBangumi(d, this.epid).season(); r(true); }).catch(e => { toast.error("获取bangumi数据出错!", e); if (config.videoLimit) { xhr({ url: Format.objUrl(\`\${config.limitServer || "https://api.global.bilibili.com"}/intl/gateway/v2/ogv/view/app/season\`, this.obj), responseType: "json", credentials: true }).then(d => { this.__INITIAL_STATE__ = new API.initialStateOfBangumi(d, this.epid).global(); API.limit = true; API.globalLimit = true; r(true); }).catch(e => { debug.error(e); }); } }); } }); if (this.__INITIAL_STATE__?.epInfo?.badge === "互动") this.stop("这似乎是个互动番剧!什么!番剧也能互动?可惜旧版播放器不支持 ಥ_ಥ"); config.bangumiEplist && this.__INITIAL_STATE__?.epList[1] && (this.__INITIAL_STATE__.special = false, this.__INITIAL_STATE__.mediaInfo.bkg_cover = undefined); this.appendIniState(); config.episodeData && API.importModule("episodeData.js"); // 显示分集数据 API.importModule("restoreData.js"); // 修复页面数据 API.switchVideo(() => { const ep = this.__INITIAL_STATE__.epList.find(d => d.cid == API.cid); ep && API.mediaSession({ title: ep.index_title || this.__INITIAL_STATE__.mediaInfo.title, artist: this.__INITIAL_STATE__.upInfo.uname, album: this.__INITIAL_STATE__.mediaInfo.title, artwork: [{ src: ep.cover }] }); }); this.flushDocument(); } appendIniState() { if (this.__INITIAL_STATE__.special) { const head = document.querySelector(".z-top-container.has-menu"); head.classList.remove("has-menu"); head.style.height = "42px"; document.querySelector("#app").classList.add("special"); } this.script.unshift({ type: "text/javascript", text: \`window.__INITIAL_STATE__=\${JSON.stringify(this.__INITIAL_STATE__)};(function(){var s;(s=document.currentScript||document.scripts[document.scripts.length-1]).parentNode.removeChild(s);}());\` }); } afterFlush() { config.enlike && API.importModule("enLike.js"); // 添加点赞功能 API.runWhile(() => document.querySelector(".new-entry"), () => document.querySelector(".new-entry")?.remove()); // 移除过期节点 if (document.compatMode === "BackCompat") { // 怪异模式下样式修复 API.addCss(".header-info .count-wrapper div, .ulike { height:18px !important; }.bili-header-m .nav-menu .profile-info .i-face { top:5px; }"); } } } new Bangumi("bangumi.html"); //# sourceURL=API://@Bilibili-Old/url/bangumi/bangumi.js`; /*!***********************!*/ /**/modules["episodeData.js"] = /*** ./dist/url/bangumi/episodeData.js ***/ `{ let first = 0; // 首p指示 API.switchVideo(async () => { try { first++; let views = document.querySelector(".view-count").querySelector("span"); let danmakus = document.querySelector(".danmu-count").querySelector("span"); if (first === 1) { // 首p时辈分总播放数和总弹幕数 views.setAttribute("title", "总播放数 " + views.innerText); danmakus.setAttribute("title", "总弹幕数 " + danmakus.innerText); debug.debug("总播放数", views.innerText, " 总弹幕数", danmakus.innerText); } let data = await xhr({ url: Format.objUrl("https://api.bilibili.com/x/web-interface/archive/stat", { "aid": String(API.aid) }), credentials: true }); // 获取分集数据 data = API.jsonCheck(data).data; let view = data.view; let danmaku = data.danmaku; view = Format.unitFormat(view); danmaku = Format.unitFormat(danmaku); views.innerText = view; danmakus.innerText = danmaku; debug.debug("播放", view + " 弹幕", danmaku); } catch (e) { debug.error("episodeData.js", e); } }); } //# sourceURL=API://@Bilibili-Old/url/bangumi/episodeData.js`; /*!***********************!*/ /**/modules["initialStateOfBangumi.js"] = /*** ./dist/url/bangumi/initialStateOfBangumi.js ***/ `class InitialStateOfBangumi { __INITIAL_STATE__ = { activity: {}, app: false, area: 0, canReview: true, epId: 0, epInfo: {}, epList: [], epStat: { isPay: true, isVip: false, payPack: 0, status: 1, vipNeedPay: false }, isPlayerTrigger: false, loginInfo: {}, mdId: 0, mediaInfo: { actors: "", alias: "", areas: [], bkg_cover: "", cover: "", evaluate: "", is_paster_ads: 0, jp_title: "", link: "", media_id: 0, mode: 1, paster_text: "", season_id: 0, season_status: 0, season_title: "", season_type: 1, square_cover: "", staff: "", style: [], title: "", total_ep: 0 }, mediaRating: {}, miniOn: 1, newestEp: {}, paster: {}, payMent: {}, payPack: {}, playerRecomList: [], pubInfo: { is_started: 1 }, recomList: [], rightsInfo: {}, seasonFollowed: false, seasonList: [], seasonStat: {}, special: false, spending: 0, sponsorTotal: { code: 0, result: { ep_bp: 0, list: [], mine: {}, users: 0 } }, sponsorTotalCount: 0, sponsorWeek: { code: 0, result: { ep_bp: 0, list: [], mine: {}, users: 0 } }, ssId: 0, ssStat: {}, upInfo: {}, userCoined: 1, userLongReview: {}, userScore: -1, userShortReview: {}, userStat: {}, ver: {} }; epId; data; constructor(data, epId) { this.epId = Number(epId) || NaN; this.data = API.jsonCheck(data).result; API.vipCid = []; } season() { const ids = this.data.episodes.reduce((s, d) => { s.push(d.ep_id); (d.badge == "会员" || d.badge_type) && API.vipCid.push(d.cid); return s; }, []); this.__INITIAL_STATE__.activity = this.data.activity || {}; this.__INITIAL_STATE__.epId = this.epId || ids[0]; this.__INITIAL_STATE__.epInfo = this.data.episodes[ids.indexOf(this.epId)] || this.data.episodes[0]; this.__INITIAL_STATE__.epList = this.data.episodes; this.__INITIAL_STATE__.mdId = this.data.media_id; this.__INITIAL_STATE__.mediaInfo.actors = this.data.actors; this.__INITIAL_STATE__.mediaInfo.alias = this.data.alias; this.__INITIAL_STATE__.mediaInfo.areas = this.data.areas; this.__INITIAL_STATE__.mediaInfo.bkg_cover = this.data.bkg_cover; this.__INITIAL_STATE__.mediaInfo.cover = this.data.cover; this.__INITIAL_STATE__.mediaInfo.evaluate = this.data.evaluate; this.__INITIAL_STATE__.mediaInfo.is_paster_ads = this.data.is_paster_ads; this.__INITIAL_STATE__.mediaInfo.jp_title = this.data.jp_title; this.__INITIAL_STATE__.mediaInfo.link = this.data.link; this.__INITIAL_STATE__.mediaInfo.media_id = this.data.media_id; this.__INITIAL_STATE__.mediaInfo.mode = this.data.mode; this.__INITIAL_STATE__.mediaInfo.paster_text = this.data.paster_text; this.__INITIAL_STATE__.mediaInfo.season_id = this.data.season_id; this.__INITIAL_STATE__.mediaInfo.season_status = this.data.season_status; this.__INITIAL_STATE__.mediaInfo.season_title = this.data.season_title; this.__INITIAL_STATE__.mediaInfo.season_type = this.data.season_type; this.__INITIAL_STATE__.mediaInfo.square_cover = this.data.square_cover; this.__INITIAL_STATE__.mediaInfo.staff = this.data.staff; this.__INITIAL_STATE__.mediaInfo.style = this.data.style; this.__INITIAL_STATE__.mediaInfo.title = this.data.title; this.__INITIAL_STATE__.mediaInfo.total_ep = this.data.total_ep; this.__INITIAL_STATE__.mediaRating = this.data.rating || {}; this.__INITIAL_STATE__.newestEp = this.data.newest_ep; this.__INITIAL_STATE__.payMent = this.data.payment || {}; this.__INITIAL_STATE__.pubInfo = this.data.publish; this.__INITIAL_STATE__.seasonList = this.data.seasons || []; this.__INITIAL_STATE__.seasonStat = this.data.stat; this.__INITIAL_STATE__.special = this.data.bkg_cover ? true : false; this.__INITIAL_STATE__.ssId = this.data.season_id; this.__INITIAL_STATE__.upInfo = this.data.up_info; return this.__INITIAL_STATE__; } global() { const ids = [], epList = []; this.data.modules.forEach((d) => { d.this.data.episodes.forEach((d) => { d.ctime = ""; d.duration = 1; d.ep_id = d.id; d.episode_status = d.status; d.index = d.title; d.index_title = d.long_title; d.mid = 2; d.page = 1; d.premiere = false; d.pub_real_time = ""; d.section_id = 0; d.section_type = 0; d.vid = ""; epList.push(d); ids.push(d.id); }); }); this.__INITIAL_STATE__.activity = this.data.activity_dialog || {}; this.__INITIAL_STATE__.epId = this.epId || ids[0]; this.__INITIAL_STATE__.epInfo = this.epId ? epList[ids.indexOf(this.epId)] : epList[0]; this.__INITIAL_STATE__.epList = epList; this.__INITIAL_STATE__.mediaInfo.actors = this.data.actor.info; this.__INITIAL_STATE__.mediaInfo.alias = this.data.alias; this.__INITIAL_STATE__.mediaInfo.areas = this.data.areas; this.__INITIAL_STATE__.mediaInfo.cover = this.data.cover; this.__INITIAL_STATE__.mediaInfo.evaluate = this.data.evaluate; this.__INITIAL_STATE__.mediaInfo.link = this.data.link; this.__INITIAL_STATE__.mediaInfo.mode = this.data.mode; this.__INITIAL_STATE__.mediaInfo.season_id = this.data.season_id; this.__INITIAL_STATE__.mediaInfo.season_status = this.data.season_status; this.__INITIAL_STATE__.mediaInfo.season_title = this.data.season_title; this.__INITIAL_STATE__.mediaInfo.staff = this.data.staff; this.__INITIAL_STATE__.mediaInfo.style = this.data.styles; this.__INITIAL_STATE__.mediaInfo.title = this.data.title; this.__INITIAL_STATE__.mediaInfo.total_ep = ids.length; this.__INITIAL_STATE__.newestEp = this.data.new_ep; this.__INITIAL_STATE__.pubInfo = this.data.publish; this.__INITIAL_STATE__.pubInfo.is_started = 1; this.__INITIAL_STATE__.rightsInfo = this.data.right; this.__INITIAL_STATE__.seasonStat = this.data.stat; this.__INITIAL_STATE__.ssId = this.data.season_id; return this.__INITIAL_STATE__; } } API.initialStateOfBangumi = InitialStateOfBangumi; //# sourceURL=API://@Bilibili-Old/url/bangumi/initialStateOfBangumi.js`; /*!***********************!*/ /**/modules["restoreData.js"] = /*** ./dist/url/bangumi/restoreData.js ***/ `{ // 修复追番数 API.xhrhook("bangumi.bilibili.com/ext/web_api/season_count?", args => { args[1] = args[1].replace('bangumi.bilibili.com/ext/web_api/season_count', 'api.bilibili.com/pgc/web/season/stat'); }, args => { const response = API.jsonCheck(args.responseText); response.result.favorites = response.result.follow; args.response = args.responseText = JSON.stringify(response); }, false); // 修复番剧推荐 API.addCss(\`#bangumi_recommend_vertial .recom-list{ height: 960px; overflow: auto; } .recom-list::-webkit-scrollbar { width: 0 !important; height: 0 !important; }\`, "recom-list"); API.runWhile(() => document.querySelector(".recom-list.clearfix"), async () => { let result = API.jsonCheck(await xhr({ url: Format.objUrl("https://api.bilibili.com/x/tag/info", { tag_name: (API.__INITIAL_STATE__).mediaInfo.title }) })); result = API.jsonCheck(await xhr({ url: Format.objUrl("https://api.bilibili.com/x/web-interface/tag/top", { tid: result.data.tag_id }) })).data; result = result.reduce((s, d) => { s = s + \`
        • \${d.title}
          \${d.title}
          \${Format.unitFormat(d.stat.view)}
          \${Format.unitFormat(d.stat.danmaku)}
        • \`; return s; }, ""); document.querySelector(".recom-list.clearfix").innerHTML = result; }); } //# sourceURL=API://@Bilibili-Old/url/bangumi/restoreData.js`; /*!***********************!*/ /**/modules["ad2info.js"] = /*** ./dist/url/index/ad2info.js ***/ `{ API.runWhile(() => document.querySelector("#bili_ad"), function () { const node = document.querySelector("#bili_ad"); const sight = node.querySelectorAll("a"); const title = node.querySelector(".name"); const technology = document.querySelector("#bili_technology").querySelector(".name"); const digital = document.querySelector("#bili_digital").querySelector(".name"); title && (title.innerText = "资讯"); sight.forEach(d => { d.href && d.href.includes("www.bilibili.com/v/ad/ad/") && (d.href = "https://www.bilibili.com/v/information/"); }); API.addElement("div", { class: "r-con" }, undefined, '

          资讯分区正式上线啦!

          ', undefined, document.querySelector("#ranking_ad")); technology.href = "//www.bilibili.com/v/knowledge/"; technology.innerHTML = "知识"; digital.href = "//www.bilibili.com/v/tech/"; digital.innerHTML = "科技"; document.querySelector(".icon.icon_t.icon-ad").setAttribute("style", "background-image: url(//cdn.jsdelivr.net/gh/MotooriKashin/Bilibili-Old/image/news.png);background-position: unset;"); }); API.runWhile(() => document.querySelector(".report-wrap-module.elevator-module"), function () { const node = document.querySelector(".report-wrap-module.elevator-module"); for (let item of node.children[1].children) { if (item.innerHTML == "广告") item.innerHTML = "资讯"; if (item.innerHTML == "科技") item.innerHTML = "知识"; if (item.innerHTML == "数码") item.innerHTML = "科技"; } }); } //# sourceURL=API://@Bilibili-Old/url/index/ad2info.js`; /*!***********************!*/ /**/modules["biliIndexRec.js"] = /*** ./dist/url/index/biliIndexRec.js ***/ `API.xhrhook("api.live.bilibili.com/room/v1/RoomRecommend/biliIndexRec", args => { 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') : args[1].replace('api.live.bilibili.com/room/v1/RoomRecommend/biliIndexRecMore', 'api.live.bilibili.com/xlive/web-interface/v1/webMain/getMoreRecList?platform=web'); }, obj => { let response = obj.responseText?.replace(/preview_banner_list/, "preview").replace(/ranking_list/, "ranking").replace(/recommend_room_list/, "recommend"); if (response) { 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; obj.response = obj.responseText = JSON.stringify(response); } }, false); //# sourceURL=API://@Bilibili-Old/url/index/biliIndexRec.js`; /*!***********************!*/ /**/modules["index.js"] = /*** ./dist/url/index/index.js ***/ `class Index extends API.rewrite { constructor(html) { super(html); this.script = [ { type: "text/javascript", src: "//static.hdslb.com/js/jquery.min.js" }, { src: "//s1.hdslb.com/bfs/seed/jinkela/header/header.js" }, { src: "//s1.hdslb.com/bfs/static/jinkela/home/1.home.4eadf4209b1762230047120e0a9945a9f3b56fd1.js", defer: "defer" }, { src: "//s1.hdslb.com/bfs/static/jinkela/home/home.4eadf4209b1762230047120e0a9945a9f3b56fd1.js", defer: "defer" }, { type: "text/javascript", src: "//s1.hdslb.com/bfs/cm/st/bundle.js", crossorigin: "" }, { type: "text/javascript", defer: "defer", charset: "utf-8", src: "//static.hdslb.com/common/js/footer.js" } ]; API.path.name = "index"; this.getIniState(); this.onload = () => { this.afterFlush(); }; } async getIniState() { const data = (await xhr({ url: "https://api.bilibili.com/x/web-show/res/locs?pf=0&ids=4694,34,31", responseType: "json" })).data; let result = { locsData: { 23: data[4694], 34: data[34], 31: data[31] } }; config.indexLoc && this.reAD(result); window.__INITIAL_STATE__ = result; API.importModule("indexSort.js"); this.flushDocument(); } reAD(data) { for (let key in data.locsData) { if (Array.isArray(data.locsData[key])) { data.locsData[key] = data.locsData[key].filter((d) => { return d.is_ad ? (debug.debug("移除广告", key, d), false) : true; }); } } } afterFlush() { // 移除无效节点 API.runWhile(() => document.querySelector(".ver"), () => document.querySelector(".ver")?.remove()); API.runWhile(() => document.querySelector("#fixed_app_download"), () => document.querySelector("#fixed_app_download")?.remove()); // 修复失效分区 API.addCss(".bili-tab.rank-tab, .bili-dropdown.rank-dropdown { pointer-events: none; }"); } } new Index("index.html"); //# sourceURL=API://@Bilibili-Old/url/index/index.js`; /*!***********************!*/ /**/modules["indexRecommend.js"] = /*** ./dist/url/index/indexRecommend.js ***/ `{ let indexRecommend, indexFlag; API.runWhile(() => document.querySelector(".bili-wrapper"), async function () { try { let node = document.querySelector(".recommend-module.clearfix"); // 父节点 let prev = API.addElement("span", { class: "rec-btn prev" }, node, undefined, undefined, document.querySelector(".rec-btn.prev")); // 替换切换按钮 let next = API.addElement("span", { class: "rec-btn next" }, node, undefined, undefined, document.querySelector(".rec-btn.next")); // 替换切换按钮 prev.innerHTML = next.innerHTML = "切换"; // 命名按钮 prev.onclick = next.onclick = async () => { // 按钮单击回调 document.querySelectorAll(".groom-module.home-card").forEach(d => d.remove()); // 移除现有数据 let wait = API.addElement("div", { class: "load-state" }, node, undefined, true); // 添加loading临时节点 wait.innerHTML = '正在加载...'; // 写入loading提示 indexRecommend = indexRecommend && indexRecommend.length > 20 ? indexRecommend : API.jsonCheck(await xhr({ url: "https://api.bilibili.com/x/web-interface/index/top/rcmd?fresh_type=3", credentials: !config.privateRecommend })).data.item; // 请求推荐数据,分情况,个性化推荐每次都请求,全站推荐只请求一次 indexFlag = indexRecommend.length < 20 ? 10 : indexFlag || ((API.uid && config.privateRecommend) ? 10 : 20); // 设置遍历起始点,个性化推荐固定为10 wait.remove(); // 移除loading节点 for (let i = indexFlag - 1; i >= indexFlag - 10; i--) { // 依次创建推荐数据,长度固定为10 API.addElement("div", { class: "groom-module home-card" }, node, undefined, true).innerHTML = \` \${indexRecommend[i].title} ">

          \${indexRecommend[i].title}

          up主:\${indexRecommend[i].owner.name}

          播放:\${Format.unitFormat(indexRecommend[i].stat.view)}

          \`; } indexFlag = indexRecommend.length < 20 ? 10 : indexFlag < 30 ? indexFlag + 10 : 10; // 对于全站推荐,刷新遍历起始点 }; prev.click(); // 移除个性化推荐 } catch (e) { debug.error("indexRecommend.js", e); } }); } //# sourceURL=API://@Bilibili-Old/url/index/indexRecommend.js`; /*!***********************!*/ /**/modules["indexSort.js"] = /*** ./dist/url/index/indexSort.js ***/ `{ API.importModule("biliIndexRec.js"); API.importModule("ad2info.js"); API.importModule("mediaRank.js"); API.importModule("indexRecommend.js"); // 广告取转资讯区 API.jsonphook(["region", "rid=165"], url => url.replace("rid=165", "rid=202"), undefined, false); // 用户热点最新投稿修复资讯区最新投稿 API.jsonphook(["newlist", "rid=165"], url => url.replace("rid=165", "rid=203"), undefined, false); // 取消原创排行榜 API.jsonphook(["region", "original=1"], url => url.replace("original=1", "original=0"), undefined, false); // 修复置顶推荐 API.jsonphook("api.bilibili.com/x/web-interface/ranking/index", url => url.replace("ranking/index", "index/top"), undefined, false); } //# sourceURL=API://@Bilibili-Old/url/index/indexSort.js`; /*!***********************!*/ /**/modules["mediaRank.js"] = /*** ./dist/url/index/mediaRank.js ***/ `{ async function fixRank(node) { const sorts = { bili_movie: ["ranking_movie", 2, "https://www.bilibili.com/ranking/cinema/23/0/3"], bili_teleplay: ["ranking_teleplay", 5, "https://www.bilibili.com/ranking/cinema/11/0/3"], bili_documentary: ["ranking_documentary", 3, "https://www.bilibili.com/ranking/cinema/177/0/3"] }; const sort = sorts[node.id]; if (!sort) return; let section = node.getElementsByClassName("sec-rank report-wrap-module zone-rank")[0]; section.innerHTML = '

          排行

            查看更多'; try { let data = await xhr({ url: Format.objUrl("https://api.bilibili.com/pgc/season/rank/web/list", { season_type: sort[1], day: '3' }) }); data = API.jsonCheck(data).data; let div = node.getElementsByClassName("bangumi-rank-list rank-list")[0]; for (let i = 0; i < 8; i++) { let li = document.createElement("li"), cl = i < 3 ? "rank-item highlight" : "rank-item", fw; li.setAttribute("class", cl); li.innerHTML = '' + (i + 1) + '

            ' + 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: ' + (API.getTotalTop(li) - 150) + 'px;'); fw.innerHTML = '
            ' + data.list[i].title + '

            ' + data.list[i].title + '

            ' + data.list[i].new_ep.index_show + '

            ' + Format.unitFormat(data.list[i].stat.view) + '' + Format.unitFormat(data.list[i].stat.danmaku) + '' + Format.unitFormat(data.list[i].stat.follow) + '
            '; document.body.appendChild(fw); }; li.onmouseout = () => fw.remove(); div.appendChild(li); } } catch (e) { debug.error("indexSort.js", e); } } API.runWhile(() => document.querySelector("#bili_movie"), () => fixRank(document.querySelector("#bili_movie"))); API.runWhile(() => document.querySelector("#bili_teleplay"), () => fixRank(document.querySelector("#bili_teleplay"))); API.runWhile(() => document.querySelector("#bili_documentary"), () => fixRank(document.querySelector("#bili_documentary"))); } //# sourceURL=API://@Bilibili-Old/url/index/mediaRank.js`; /*!***********************!*/ /**/modules["live.js"] = /*** ./dist/url/live/live.js ***/ `{ config.liveP2p && API.importModule("WebRTC.js"); config.sleepCheck && API.importModule("sleepCheck.js"); API.runWhile(() => document.querySelector(".web-player-icon-roomStatus"), () => document.querySelector(".web-player-icon-roomStatus")?.remove()); } //# sourceURL=API://@Bilibili-Old/url/live/live.js`; /*!***********************!*/ /**/modules["sleepCheck.js"] = /*** ./dist/url/live/sleepCheck.js ***/ `{ const fun = setInterval; let flag = 0; window.setInterval = (...args) => { if (args[1] && args[1] == 300000 && args[0] && args[0].toString() == "function(){e.triggerSleepCallback()}") { if (!flag) { toast.warning("成功阻止直播间挂机检测!"); flag++; } return Number.MIN_VALUE; } return fun.call(window, ...args); }; } //# sourceURL=API://@Bilibili-Old/url/live/sleepCheck.js`; /*!***********************!*/ /**/modules["WebRTC.js"] = /*** ./dist/url/live/WebRTC.js ***/ `if (typeof navigator.getUserMedia !== "undefined") navigator.getUserMedia = undefined; if (typeof window.MediaStreamTrack !== "undefined") window.MediaStreamTrack = undefined; if (typeof window.RTCPeerConnection !== "undefined") window.RTCPeerConnection = undefined; if (typeof window.RTCSessionDescription !== "undefined") window.RTCSessionDescription = undefined; if (typeof navigator.mozGetUserMedia !== "undefined") navigator.mozGetUserMedia = undefined; if (typeof window.mozMediaStreamTrack !== "undefined") window.mozMediaStreamTrack = undefined; if (typeof window.mozRTCPeerConnection !== "undefined") window.mozRTCPeerConnection = undefined; if (typeof window.mozRTCSessionDescription !== "undefined") window.mozRTCSessionDescription = undefined; if (typeof navigator.webkitGetUserMedia !== "undefined") navigator.webkitGetUserMedia = undefined; if (typeof window.webkitMediaStreamTrack !== "undefined") window.webkitMediaStreamTrack = undefined; if (typeof window.webkitRTCPeerConnection !== "undefined") window.webkitRTCPeerConnection = undefined; if (typeof window.webkitRTCSessionDescription !== "undefined") window.webkitRTCSessionDescription = undefined; //# sourceURL=API://@Bilibili-Old/url/live/WebRTC.js`; /*!***********************!*/ /**/modules["album.js"] = /*** ./dist/url/space/album.js ***/ `API.xhrhook("api.bilibili.com/x/dynamic/feed/draw/doc_list", undefined, obj => { const response = JSON.parse(obj.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); }, false); //# sourceURL=API://@Bilibili-Old/url/space/album.js`; /*!***********************!*/ /**/modules["jointime.js"] = /*** ./dist/url/space/jointime.js ***/ `(async function () { try { if (!document.querySelector(".user-info-title")) { await new Promise(r => { API.runWhile(() => document.querySelector(".user-info-title"), r); }); } let data = API.jsonCheck(await xhr.GM({ url: Format.objUrl("https://account.bilibili.com/api/member/getCardByMid", { "mid": API.mid }) })); let jointime = Format.timeFormat(data.card.regtime * 1000, true); let node = document.querySelector(".user-info-title"); API.addElement("span", { class: "info-jointime" }, node, jointime); } catch (e) { toast.error("jsontime.js", e); } })(); //# sourceURL=API://@Bilibili-Old/url/space/jointime.js`; /*!***********************!*/ /**/modules["lostVideo.js"] = /*** ./dist/url/space/lostVideo.js ***/ `{ async function getLostVideo(aid) { let result = []; // 失效视频信息缓存 try { // 尝试访问Biliplus let data = await xhr.GM({ url: \`https://www.biliplus.com/video/av\${aid}\` }); if (data.match(/\\.+?\\ \\-\\ AV/)) { result[0] = data.match(/\\.+?\\ \\-\\ AV/)[0].replace(//, "").replace(/ - AV/, ""); result[1] = data.match(/\\<img style=\\"display:none\\"\\ src=\\".+?\\"\\ alt/)[0].replace(/<img style="display:none" src="/, "").replace(/" alt/, ""); } } catch (e) { debug.error("lostVideo.js", e); } if (!result[0] || !result[1]) { try { // 标题或封面无效,尝试访问Biliplus CID缓存库 let data = await xhr.GM({ url: \`https://www.biliplus.com/all/video/av\${aid}/\` }); if (data.match('/api/view_all?')) { data = data.match(/\\/api\\/view_all\\?.+?\\',cloudmoe/)[0].replace(/\\',cloudmoe/, ""); data = await xhr.GM({ url: \`//www.biliplus.com\${data}\` }); data = API.jsonCheck(data).data; result[0] = result[0] || data.info.title; result[1] = result[1] || data.info.pic; } } catch (e) { debug.error("lostVideo.js", e); } } if (!result[0] || !result[1]) { try { // 标题或封面依旧无效,尝试访问jijidown let data = await xhr.GM({ url: \`https://www.jijidown.com/video/\${aid}\` }); if (data.match('window._INIT')) { result[0] = result[0] || data.match(/\\<title\\>.+?\\-哔哩哔哩唧唧/)[0].replace(/<title>/, "").replace(/-哔哩哔哩唧唧/, ""); result[1] = result[1] || data.match(/\\"img\\":\\ \\".+?\\",/)[0].match(/http.+?\\",/)[0].replace(/",/, ""); } } catch (e) { debug.error("lostVideo.js", e); } } result[0] = result[0] || \`av\${aid}\`; // 无法获取有效数据,将标题改为av号 result[1] = result[1] ? result[1].replace("http:", "") : "//i0.hdslb.com/bfs/archive/be27fd62c99036dce67efface486fb0a88ffed06.jpg"; //无法获取有效数据,将封面改为哭脸 return result; } API.observerAddedNodes((node) => { if (/section channel guest/.test(node.className)) { let items = node.querySelectorAll(".small-item.disabled"); items.forEach(d => { let aid = d.getAttribute("data-aid"); // 获取aid aid = Number(aid) || API.abv(aid); // 转化为数字 d.setAttribute("class", "small-item fakeDanmu-item"); d.setAttribute("data-aid", aid); d.children[0].href = \`//www.bilibili.com/video/av\${aid}\`; d.children[1].href = \`//www.bilibili.com/video/av\${aid}\`; d.children[0].setAttribute("target", "_blank"); d.children[1].setAttribute("target", "_blank"); d.children[0].setAttribute("class", "cover cover-normal"); d.children[1].setAttribute("style", "text-decoration : line-through;color : #ff0000;"); getLostVideo(aid).then(data => { d.children[1].setAttribute("title", data[0]); d.children[1].text = data[0]; d.children[0].children[0].alt = data[0]; d.children[0].children[0].src = data[1]; }); }); } if (/small-item disabled/.test(node.className)) { let aid = node.getAttribute("data-aid"); // 获取aid aid = Number(aid) || API.abv(aid); // 转化为数字 node.setAttribute("class", "small-item fakeDanmu-item"); node.setAttribute("data-aid", aid); node.children[0].href = \`//www.bilibili.com/video/av\${aid}\`; node.children[1].href = \`//www.bilibili.com/video/av\${aid}\`; node.children[0].setAttribute("target", "_blank"); node.children[1].setAttribute("target", "_blank"); node.children[0].setAttribute("class", "cover cover-normal"); node.children[1].setAttribute("style", "text-decoration : line-through;color : #ff0000;"); getLostVideo(aid).then(data => { node.children[1].setAttribute("title", data[0]); node.children[1].text = data[0]; node.children[0].children[0].alt = data[0]; node.children[0].children[0].src = data[1]; }); } }); } //# sourceURL=API://@Bilibili-Old/url/space/lostVideo.js`; /*!***********************!*/ /**/modules["midInfo.js"] = /*** ./dist/url/space/midInfo.js ***/ `{ const response = API.getModule("mid.json"); response.data.mid = API.mid; switch (Number(API.mid)) { case 11783021: response.data.name = "哔哩哔哩番剧出差"; response.data.official.desc = "哔哩哔哩番剧出差 官方帐号"; break; case 1988098633: response.data.name = "b站_戲劇咖"; response.data.official.desc = "b站_戲劇咖 官方帐号"; break; case 2042149112: response.data.name = "b站_綜藝咖"; response.data.official.desc = "b站_綜藝咖 官方帐号"; break; } API.xhrhook("api.bilibili.com/x/space/acc/info", undefined, obj => { if (obj.responseText && obj.responseText.includes("-404")) { obj.response = obj.responseText = JSON.stringify(response); toast.warning("该用户被404,已使用缓存数据恢复访问!"); } }, false); } //# sourceURL=API://@Bilibili-Old/url/space/midInfo.js`; /*!***********************!*/ /**/modules["space.js"] = /*** ./dist/url/space/space.js ***/ `{ API.mid = (API.path[3] && API.path[3].split("?")[0]) || API.mid; config.errands && (API.mid == 11783021 || API.mid == 1988098633 || API.mid == 2042149112) && API.importModule("midInfo.js"); config.album && API.importModule("album.js"); // 相簿重定向 config.jointime && API.importModule("jointime.js"); // 注册时间 config.lostVideo && API.importModule("lostVideo.js"); // 失效视频 } //# sourceURL=API://@Bilibili-Old/url/space/space.js`; /*!***********************!*//** * 脚本主入口,因为运行上下文为独立的沙盒,功能实现极不方便,实际负责提供接口和切换运行上下文并引导实际入口`main`。 */ (function () { new Function("GM", "modules", "config", "debug", "Format", "toast", "xhr", modules["main.js"])(GM, modules, config, debug, Format, toast, xhr); })();