Greasy Fork is available in English.
bilibili免登录,看高清直播,看高清视频,随时看所有评论。观看历史记录,收藏功能正在支持中,欢迎来给项目star和pr!通过拦截一些特定 Bilibili 接口请求或响应,让你的体验能够像登录用户一样丝滑!
// ==UserScript== // @name 哔哩免登录看评论+1080p视频+免弹窗 // @namespace vruses // @version 2.0.4 // @author <[email protected]> // @description bilibili免登录,看高清直播,看高清视频,随时看所有评论。观看历史记录,收藏功能正在支持中,欢迎来给项目star和pr!通过拦截一些特定 Bilibili 接口请求或响应,让你的体验能够像登录用户一样丝滑! // @license MIT // @icon data:image/jpeg;base64,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 // @homepage https://github.com/vruses/bili-api-interceptor // @source https://github.com/vruses/bili-api-interceptor.git // @supportURL https://github.com/vruses/bili-api-interceptor // @match *://*.bilibili.com/* // @grant none // @run-at document-start // ==/UserScript== (function () { 'use strict'; var __defProp = Object.defineProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); var freeGlobal = typeof global == "object" && global && global.Object === Object && global; var freeSelf = typeof self == "object" && self && self.Object === Object && self; var root = freeGlobal || freeSelf || Function("return this")(); var Symbol$1 = root.Symbol; var objectProto$1 = Object.prototype; var hasOwnProperty = objectProto$1.hasOwnProperty; var nativeObjectToString$1 = objectProto$1.toString; var symToStringTag$1 = Symbol$1 ? Symbol$1.toStringTag : void 0; function getRawTag(value) { var isOwn = hasOwnProperty.call(value, symToStringTag$1), tag = value[symToStringTag$1]; try { value[symToStringTag$1] = void 0; var unmasked = true; } catch (e) { } var result = nativeObjectToString$1.call(value); if (unmasked) { if (isOwn) { value[symToStringTag$1] = tag; } else { delete value[symToStringTag$1]; } } return result; } var objectProto = Object.prototype; var nativeObjectToString = objectProto.toString; function objectToString(value) { return nativeObjectToString.call(value); } var nullTag = "[object Null]", undefinedTag = "[object Undefined]"; var symToStringTag = Symbol$1 ? Symbol$1.toStringTag : void 0; function baseGetTag(value) { if (value == null) { return value === void 0 ? undefinedTag : nullTag; } return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString(value); } function isObjectLike(value) { return value != null && typeof value == "object"; } var symbolTag = "[object Symbol]"; function isSymbol(value) { return typeof value == "symbol" || isObjectLike(value) && baseGetTag(value) == symbolTag; } var reWhitespace = /\s/; function trimmedEndIndex(string) { var index = string.length; while (index-- && reWhitespace.test(string.charAt(index))) { } return index; } var reTrimStart = /^\s+/; function baseTrim(string) { return string ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, "") : string; } function isObject(value) { var type = typeof value; return value != null && (type == "object" || type == "function"); } var NAN = 0 / 0; var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; var reIsBinary = /^0b[01]+$/i; var reIsOctal = /^0o[0-7]+$/i; var freeParseInt = parseInt; function toNumber(value) { if (typeof value == "number") { return value; } if (isSymbol(value)) { return NAN; } if (isObject(value)) { var other = typeof value.valueOf == "function" ? value.valueOf() : value; value = isObject(other) ? other + "" : other; } if (typeof value != "string") { return value === 0 ? value : +value; } value = baseTrim(value); var isBinary = reIsBinary.test(value); return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value; } var INFINITY = 1 / 0, MAX_INTEGER = 17976931348623157e292; function toFinite(value) { if (!value) { return value === 0 ? value : 0; } value = toNumber(value); if (value === INFINITY || value === -INFINITY) { var sign = value < 0 ? -1 : 1; return sign * MAX_INTEGER; } return value === value ? value : 0; } var asyncTag = "[object AsyncFunction]", funcTag = "[object Function]", genTag = "[object GeneratorFunction]", proxyTag = "[object Proxy]"; function isFunction(value) { if (!isObject(value)) { return false; } var tag = baseGetTag(value); return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; } var MAX_SAFE_INTEGER$1 = 9007199254740991; var reIsUint = /^(?:0|[1-9]\d*)$/; function isIndex(value, length) { var type = typeof value; length = length == null ? MAX_SAFE_INTEGER$1 : length; return !!length && (type == "number" || type != "symbol" && reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length); } function eq(value, other) { return value === other || value !== value && other !== other; } var MAX_SAFE_INTEGER = 9007199254740991; function isLength(value) { return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; } function isArrayLike(value) { return value != null && isLength(value.length) && !isFunction(value); } function isIterateeCall(value, index, object) { if (!isObject(object)) { return false; } var type = typeof index; if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) { return eq(object[index], value); } return false; } var nativeFloor = Math.floor, nativeRandom$1 = Math.random; function baseRandom(lower, upper) { return lower + nativeFloor(nativeRandom$1() * (upper - lower + 1)); } var freeParseFloat = parseFloat; var nativeMin = Math.min, nativeRandom = Math.random; function random(lower, upper, floating) { if (floating && typeof floating != "boolean" && isIterateeCall(lower, upper, floating)) { upper = floating = void 0; } if (floating === void 0) { if (typeof upper == "boolean") { floating = upper; upper = void 0; } else if (typeof lower == "boolean") { floating = lower; lower = void 0; } } if (lower === void 0 && upper === void 0) { lower = 0; upper = 1; } else { lower = toFinite(lower); if (upper === void 0) { upper = lower; lower = 0; } else { upper = toFinite(upper); } } if (lower > upper) { var temp = lower; lower = upper; upper = temp; } if (floating || lower % 1 || upper % 1) { var rand = nativeRandom(); return nativeMin(lower + rand * (upper - lower + freeParseFloat("1e-" + ((rand + "").length - 1))), upper); } return baseRandom(lower, upper); } let isInterceptActive = false; let wsOriginalSend = null; function toggleIntercept() { if (!isInterceptActive) { wsOriginalSend = WebSocket.prototype.send; isInterceptActive = true; WebSocket.prototype.send = function(data) { if (data instanceof ArrayBuffer) { const view = new DataView(data); if (view.getUint32(8, false) === 7) { return wsOriginalSend.call(this, modifyUidPacket(data)); } } return wsOriginalSend.call(this, data); }; } else { if (wsOriginalSend) { WebSocket.prototype.send = wsOriginalSend; } isInterceptActive = false; wsOriginalSend = null; } } function modifyUidPacket(data) { const newBuffer = data.slice(); const jsonStart = 16; const jsonBytes = new Uint8Array(newBuffer, jsonStart); const jsonString = new TextDecoder().decode(jsonBytes); const jsonObj = JSON.parse(jsonString); jsonObj.uid = 0; const newJsonString = JSON.stringify(jsonObj); const newJsonBytes = new TextEncoder().encode(newJsonString); const newPacket = new ArrayBuffer(16 + newJsonBytes.length); const newView = new DataView(newPacket); const originalView = new DataView(data); for (let i = 0; i < 16; i++) { newView.setUint8(i, originalView.getUint8(i)); } newView.setUint32(0, newJsonBytes.length + 16, false); new Uint8Array(newPacket, 16).set(newJsonBytes); return newPacket; } // @license GNU LGPL-3.0 const ajaxHooker = (() => { const version = "1.4.7"; const hookInst = { hookFns: [], filters: [] }; const win = window.unsafeWindow || document.defaultView || window; let winAh = win.__ajaxHooker; const resProto = win.Response.prototype; const xhrResponses = ["response", "responseText", "responseXML"]; const fetchResponses = ["arrayBuffer", "blob", "formData", "json", "text"]; const xhrExtraProps = ["responseType", "timeout", "withCredentials"]; const fetchExtraProps = [ "cache", "credentials", "integrity", "keepalive", "mode", "priority", "redirect", "referrer", "referrerPolicy", "signal" ]; const xhrAsyncEvents = ["readystatechange", "load", "loadend"]; const getType = {}.toString.call.bind({}.toString); const getDescriptor = Object.getOwnPropertyDescriptor.bind(Object); const emptyFn = () => { }; const errorFn = (e) => console.error(e); function isThenable(obj) { return obj && ["object", "function"].includes(typeof obj) && typeof obj.then === "function"; } function catchError(fn, ...args) { try { const result = fn(...args); if (isThenable(result)) return result.then(null, errorFn); return result; } catch (err) { console.error(err); } } function defineProp(obj, prop, getter, setter) { Object.defineProperty(obj, prop, { configurable: true, enumerable: true, get: getter, set: setter }); } function readonly(obj, prop, value = obj[prop]) { defineProp(obj, prop, () => value, emptyFn); } function writable(obj, prop, value = obj[prop]) { Object.defineProperty(obj, prop, { configurable: true, enumerable: true, writable: true, value }); } function parseHeaders(obj) { const headers = {}; switch (getType(obj)) { case "[object String]": for (const line of obj.trim().split(/[\r\n]+/)) { const [header, value] = line.split(new RegExp("(?<=^[^:]+)\\s*:\\s*")); if (!value) continue; const lheader = header.toLowerCase(); headers[lheader] = lheader in headers ? `${headers[lheader]}, ${value}` : value; } break; case "[object Headers]": for (const [key, val] of obj) { headers[key] = val; } break; case "[object Object]": return { ...obj }; } return headers; } function stopImmediatePropagation() { this.ajaxHooker_isStopped = true; } class SyncThenable { then(fn) { fn && fn(); return new SyncThenable(); } } class AHRequest { constructor(request) { this.request = request; this.requestClone = { ...this.request }; } _recoverRequestKey(key) { if (key in this.requestClone) this.request[key] = this.requestClone[key]; else delete this.request[key]; } shouldFilter(filters) { const { type, url, method, async } = this.request; return filters.length && !filters.find((obj) => { switch (true) { case (obj.type && obj.type !== type): case (getType(obj.url) === "[object String]" && !url.includes(obj.url)): case (getType(obj.url) === "[object RegExp]" && !obj.url.test(url)): case (obj.method && obj.method.toUpperCase() !== method.toUpperCase()): case ("async" in obj && obj.async !== async): return false; } return true; }); } waitForRequestKeys() { if (!this.request.async) { win.__ajaxHooker.hookInsts.forEach(({ hookFns, filters }) => { if (this.shouldFilter(filters)) return; hookFns.forEach((fn) => { if (getType(fn) === "[object Function]") catchError(fn, this.request); }); for (const key in this.request) { if (isThenable(this.request[key])) this._recoverRequestKey(key); } }); return new SyncThenable(); } const promises = []; const ignoreKeys = /* @__PURE__ */ new Set(["type", "async", "response"]); win.__ajaxHooker.hookInsts.forEach(({ hookFns, filters }) => { if (this.shouldFilter(filters)) return; promises.push( Promise.all(hookFns.map((fn) => catchError(fn, this.request))).then(() => { const requestKeys = []; for (const key in this.request) !ignoreKeys.has(key) && requestKeys.push(key); return Promise.all( requestKeys.map( (key) => Promise.resolve(this.request[key]).then( (val) => this.request[key] = val, () => this._recoverRequestKey(key) ) ) ); }) ); }); return Promise.all(promises); } waitForResponseKeys(response) { const responseKeys = this.request.type === "xhr" ? xhrResponses : fetchResponses; if (!this.request.async) { if (getType(this.request.response) === "[object Function]") { catchError(this.request.response, response); responseKeys.forEach((key) => { if ("get" in getDescriptor(response, key) || isThenable(response[key])) { delete response[key]; } }); } return new SyncThenable(); } return Promise.resolve(catchError(this.request.response, response)).then( () => Promise.all( responseKeys.map((key) => { const descriptor = getDescriptor(response, key); if (descriptor && "value" in descriptor) { return Promise.resolve(descriptor.value).then( (val) => response[key] = val, () => delete response[key] ); } else { delete response[key]; } }) ) ); } } const proxyHandler = { get(target, prop) { const descriptor = getDescriptor(target, prop); if (descriptor && !descriptor.configurable && !descriptor.writable && !descriptor.get) { return target[prop]; } const ah = target.__ajaxHooker; if (ah && ah.proxyProps) { if (prop in ah.proxyProps) { const pDescriptor = ah.proxyProps[prop]; if ("get" in pDescriptor) return pDescriptor.get(); if (typeof pDescriptor.value === "function") return pDescriptor.value.bind(ah); return pDescriptor.value; } if (typeof target[prop] === "function") return target[prop].bind(target); } return target[prop]; }, set(target, prop, value) { const descriptor = getDescriptor(target, prop); if (descriptor && !descriptor.configurable && !descriptor.writable && !descriptor.set) { return true; } const ah = target.__ajaxHooker; if (ah && ah.proxyProps && prop in ah.proxyProps) { const pDescriptor = ah.proxyProps[prop]; pDescriptor.set ? pDescriptor.set(value) : pDescriptor.value = value; } else { target[prop] = value; } return true; } }; class XhrHooker { constructor(xhr) { Object.assign(this, { originalXhr: xhr, proxyXhr: new Proxy(xhr, proxyHandler), resThenable: new SyncThenable(), proxyProps: {}, proxyEvents: {} }); xhr.addEventListener("readystatechange", (e) => { if (this.proxyXhr.readyState === 4 && this.request && typeof this.request.response === "function") { const response = { finalUrl: this.proxyXhr.responseURL, status: this.proxyXhr.status, responseHeaders: parseHeaders(this.proxyXhr.getAllResponseHeaders()) }; const tempValues = {}; for (const key of xhrResponses) { try { tempValues[key] = this.originalXhr[key]; } catch (err) { } defineProp( response, key, () => { return response[key] = tempValues[key]; }, (val) => { delete response[key]; response[key] = val; } ); } this.resThenable = new AHRequest(this.request).waitForResponseKeys(response).then(() => { for (const key of xhrResponses) { this.proxyProps[key] = { get: () => { if (!(key in response)) response[key] = tempValues[key]; return response[key]; } }; } }); } this.dispatchEvent(e); }); xhr.addEventListener("load", (e) => this.dispatchEvent(e)); xhr.addEventListener("loadend", (e) => this.dispatchEvent(e)); for (const evt of xhrAsyncEvents) { const onEvt = `on${evt}`; this.proxyProps[onEvt] = { get: () => this.proxyEvents[onEvt] || null, set: (val) => this.addEvent(onEvt, val) }; } for (const method of ["setRequestHeader", "addEventListener", "removeEventListener", "open", "send"]) { this.proxyProps[method] = { value: this[method] }; } } toJSON() { } // Converting circular structure to JSON addEvent(type, event) { if (type.startsWith("on")) { this.proxyEvents[type] = typeof event === "function" ? event : null; } else { if (typeof event === "object" && event !== null) event = event.handleEvent; if (typeof event !== "function") return; this.proxyEvents[type] = this.proxyEvents[type] || /* @__PURE__ */ new Set(); this.proxyEvents[type].add(event); } } removeEvent(type, event) { if (type.startsWith("on")) { this.proxyEvents[type] = null; } else { if (typeof event === "object" && event !== null) event = event.handleEvent; this.proxyEvents[type] && this.proxyEvents[type].delete(event); } } dispatchEvent(e) { e.stopImmediatePropagation = stopImmediatePropagation; defineProp(e, "target", () => this.proxyXhr); defineProp(e, "currentTarget", () => this.proxyXhr); defineProp(e, "srcElement", () => this.proxyXhr); this.proxyEvents[e.type] && this.proxyEvents[e.type].forEach((fn) => { this.resThenable.then(() => !e.ajaxHooker_isStopped && fn.call(this.proxyXhr, e)); }); if (e.ajaxHooker_isStopped) return; const onEvent = this.proxyEvents[`on${e.type}`]; onEvent && this.resThenable.then(onEvent.bind(this.proxyXhr, e)); } setRequestHeader(header, value) { this.originalXhr.setRequestHeader(header, value); if (!this.request) return; const headers = this.request.headers; headers[header] = header in headers ? `${headers[header]}, ${value}` : value; } addEventListener(...args) { if (xhrAsyncEvents.includes(args[0])) { this.addEvent(args[0], args[1]); } else { this.originalXhr.addEventListener(...args); } } removeEventListener(...args) { if (xhrAsyncEvents.includes(args[0])) { this.removeEvent(args[0], args[1]); } else { this.originalXhr.removeEventListener(...args); } } open(method, url, async = true, ...args) { this.request = { type: "xhr", url: url.toString(), method: method.toUpperCase(), abort: false, headers: {}, data: null, response: null, async: !!async }; this.openArgs = args; this.resThenable = new SyncThenable(); ["responseURL", "readyState", "status", "statusText", ...xhrResponses].forEach((key) => { delete this.proxyProps[key]; }); return this.originalXhr.open(method, url, async, ...args); } send(data) { const xhr = this.originalXhr; const request = this.request; if (!request) return xhr.send(data); request.data = data; new AHRequest(request).waitForRequestKeys().then(() => { if (request.abort) { if (typeof request.response === "function") { Object.assign(this.proxyProps, { responseURL: { value: request.url }, readyState: { value: 4 }, status: { value: 200 }, statusText: { value: "OK" } }); xhrAsyncEvents.forEach((evt) => xhr.dispatchEvent(new Event(evt))); } } else { xhr.open(request.method, request.url, request.async, ...this.openArgs); for (const header in request.headers) { xhr.setRequestHeader(header, request.headers[header]); } for (const prop of xhrExtraProps) { if (prop in request) xhr[prop] = request[prop]; } xhr.send(request.data); } }); } } function fakeXHR() { const xhr = new winAh.realXHR(); if ("__ajaxHooker" in xhr) console.warn("检测到不同版本的ajaxHooker,可能发生冲突!"); xhr.__ajaxHooker = new XhrHooker(xhr); return xhr.__ajaxHooker.proxyXhr; } fakeXHR.prototype = win.XMLHttpRequest.prototype; Object.keys(win.XMLHttpRequest).forEach((key) => fakeXHR[key] = win.XMLHttpRequest[key]); function fakeFetch(url, options = {}) { if (!url) return winAh.realFetch.call(win, url, options); return new Promise(async (resolve, reject) => { const init = {}; if (getType(url) === "[object Request]") { init.method = url.method; init.headers = url.headers; if (url.body) init.body = await url.arrayBuffer(); for (const prop of fetchExtraProps) init[prop] = url[prop]; url = url.url; } url = url.toString(); Object.assign(init, options); init.method = init.method || "GET"; init.headers = init.headers || {}; const request = { type: "fetch", url, method: init.method.toUpperCase(), abort: false, headers: parseHeaders(init.headers), data: init.body, response: null, async: true }; const req = new AHRequest(request); await req.waitForRequestKeys(); if (request.abort) { if (typeof request.response === "function") { const response = { finalUrl: request.url, status: 200, responseHeaders: {} }; await req.waitForResponseKeys(response); const key = fetchResponses.find((k) => k in response); let val = response[key]; if (key === "json" && typeof val === "object") { val = catchError(JSON.stringify.bind(JSON), val); } const res = new Response(val, { status: 200, statusText: "OK" }); defineProp(res, "type", () => "basic"); defineProp(res, "url", () => request.url); resolve(res); } else { reject(new DOMException("aborted", "AbortError")); } return; } init.method = request.method; init.headers = request.headers; init.body = request.data; for (const prop of fetchExtraProps) { if (prop in request) init[prop] = request[prop]; } winAh.realFetch.call(win, request.url, init).then((res) => { if (typeof request.response === "function") { const response = { finalUrl: res.url, status: res.status, responseHeaders: parseHeaders(res.headers) }; fetchResponses.forEach( (key) => res[key] = function() { if (key in response) return Promise.resolve(response[key]); return resProto[key].call(this).then((val) => { response[key] = val; return req.waitForResponseKeys(response).then(() => key in response ? response[key] : val); }); } ); } resolve(res); }, reject); }); } function fakeFetchClone() { const descriptors = Object.getOwnPropertyDescriptors(this); const res = winAh.realFetchClone.call(this); Object.defineProperties(res, descriptors); return res; } winAh = win.__ajaxHooker = winAh || { version, fakeXHR, fakeFetch, fakeFetchClone, realXHR: win.XMLHttpRequest, realFetch: win.fetch, realFetchClone: resProto.clone, hookInsts: /* @__PURE__ */ new Set() }; if (winAh.version !== version) console.warn("检测到不同版本的ajaxHooker,可能发生冲突!"); win.XMLHttpRequest = winAh.fakeXHR; win.fetch = winAh.fakeFetch; resProto.clone = winAh.fakeFetchClone; winAh.hookInsts.add(hookInst); class AHFunction extends Function { call(thisArg, ...args) { if (thisArg && thisArg.__ajaxHooker && thisArg.__ajaxHooker.proxyXhr === thisArg) { thisArg = thisArg.__ajaxHooker.originalXhr; } return Reflect.apply(this, thisArg, args); } apply(thisArg, args) { if (thisArg && thisArg.__ajaxHooker && thisArg.__ajaxHooker.proxyXhr === thisArg) { thisArg = thisArg.__ajaxHooker.originalXhr; } return Reflect.apply(this, thisArg, args || []); } } function hookSecsdk(csrf) { Object.setPrototypeOf(csrf.nativeXMLHttpRequestSetRequestHeader, AHFunction.prototype); Object.setPrototypeOf(csrf.nativeXMLHttpRequestOpen, AHFunction.prototype); Object.setPrototypeOf(csrf.nativeXMLHttpRequestSend, AHFunction.prototype); } if (win.secsdk) { if (win.secsdk.csrf && win.secsdk.csrf.nativeXMLHttpRequestOpen) hookSecsdk(win.secsdk.csrf); } else { defineProp(win, "secsdk", emptyFn, (secsdk) => { delete win.secsdk; win.secsdk = secsdk; defineProp(secsdk, "csrf", emptyFn, (csrf) => { delete secsdk.csrf; secsdk.csrf = csrf; if (csrf.nativeXMLHttpRequestOpen) hookSecsdk(csrf); }); }); } return { hook: (fn) => hookInst.hookFns.push(fn), filter: (arr) => { if (Array.isArray(arr)) hookInst.filters = arr; }, protect: () => { readonly(win, "XMLHttpRequest", winAh.fakeXHR); readonly(win, "fetch", winAh.fakeFetch); readonly(resProto, "clone", winAh.fakeFetchClone); }, unhook: () => { winAh.hookInsts.delete(hookInst); if (!winAh.hookInsts.size) { writable(win, "XMLHttpRequest", winAh.realXHR); writable(win, "fetch", winAh.realFetch); writable(resProto, "clone", winAh.realFetchClone); delete win.__ajaxHooker; } } }; })(); const _RequestHooker = class _RequestHooker { constructor() { __publicField(this, "hooks", /* @__PURE__ */ new Set()); __publicField(this, "isHooked", false); } /** * 获取单例实例 */ static getInstance() { if (!_RequestHooker.instance) { _RequestHooker.instance = new _RequestHooker(); } return _RequestHooker.instance; } /** * 添加请求钩子函数 * @param fns 一个或多个请求处理函数 */ add(...fns) { fns.forEach((fn) => { this.hooks.add(fn); }); this.ensureHooked(); } /** * 移除请求钩子函数 * @param fn 要移除的函数 */ remove(fn) { this.hooks.delete(fn); } /** * 清空所有钩子函数 */ clear() { this.hooks.clear(); } /** * ajaxHooker.hook 只执行一次就行 */ ensureHooked() { if (this.isHooked) return; this.isHooked = true; ajaxHooker.hook((request) => { this.hooks.forEach((hook) => { hook(request); }); }); } }; __publicField(_RequestHooker, "instance", null); let RequestHooker = _RequestHooker; function onRequest(...args) { RequestHooker.getInstance().add(...args); } const useSearch = (request) => { if (!request.url.includes("/api.bilibili.comx/web-interface/search")) return; request.url = request.url.replace(/\.com(?!\/)/, ".com/"); }; onRequest(useSearch); function toResult(data, code = 0, message = "success", ttl = 1) { return { code, message, ttl, data }; } const mockUserInfo$1 = { isLogin: true, email_verified: 1, face: "https://i0.hdslb.com/bfs/face/0c84b9f4ad546d3f20324809d45fc439a2a8ddab.jpg", face_nft: 0, face_nft_type: 0, level_info: { current_level: 6, current_min: 28800, current_exp: 29050, next_exp: "--" }, mid: 3493281916783362, mobile_verified: 1, money: 9999.99, moral: 70, official: { role: 0, title: "", desc: "", type: -1 }, officialVerify: { type: -1, desc: "" }, pendant: { pid: 0, name: "", image: "", expire: 0, image_enhance: "", image_enhance_frame: "", n_pid: 0 }, scores: 0, uname: "bilibili", vipDueDate: 16747488e5, vipStatus: 0, vipType: 1, vip_pay_type: 0, vip_theme_type: 0, vip_label: { path: "", text: "", label_theme: "", text_color: "", bg_style: 0, bg_color: "", border_color: "", use_img_label: true, img_label_uri_hans: "", img_label_uri_hant: "", img_label_uri_hans_static: "", img_label_uri_hant_static: "" }, vip_avatar_subscript: 0, vip_nickname_color: "", vip: { type: 1, status: 0, due_date: 16747488e5, vip_pay_type: 0, theme_type: 0, label: { path: "", text: "", label_theme: "", text_color: "", bg_style: 0, bg_color: "", border_color: "", use_img_label: true, img_label_uri_hans: "", img_label_uri_hant: "", img_label_uri_hans_static: "", img_label_uri_hant_static: "" }, avatar_subscript: 0, nickname_color: "", role: 0, avatar_subscript_url: "", tv_vip_status: 0, tv_vip_pay_type: 0, tv_due_date: 0, avatar_icon: { icon_resource: {} } }, wallet: { mid: 3493281916783362, bcoin_balance: 0, coupon_balance: 0, coupon_due_time: 0 }, has_shop: false, shop_url: "", answer_status: 0, is_senior_member: 1, wbi_img: { img_url: "", sub_url: "" }, is_jury: false, name_render: null }; const mockUserInfoResult = toResult(mockUserInfo$1); const useNav = (request) => { if (!request.url.includes("/x/web-interface/nav")) return; if (request.type === "xhr") { request.response = (res) => { res.responseText = JSON.stringify(mockUserInfoResult); }; } if (request.type === "fetch") { request.response = (res) => { res.json = mockUserInfoResult; }; } }; onRequest(useNav); const historyList = { cursor: { max: 1, view_at: 0, business: "archive", ps: 20 }, tab: [ { type: "archive", name: "视频" }, { type: "live", name: "直播" }, { type: "article", name: "专栏" } ], list: [] }; const historyListResult = toResult(historyList); const useHistory = (request) => { if (!request.url.includes("/x/web-interface/history/cursor")) return; if (request.type === "xhr") return; request.response = (res) => { if (!(res == null ? void 0 : res.json)) return; res.json = historyListResult; }; }; onRequest(useHistory); const useWebKey = (key_url) => { return key_url.slice(key_url.lastIndexOf("/") + 1, key_url.lastIndexOf(".")); }; const web_key_urls = { img_key_url: localStorage.getItem("wbi_img_url") ?? "", sub_key_url: localStorage.getItem("wbi_sub_url") ?? "" }; const img_key = useWebKey(web_key_urls.img_key_url); const sub_key = useWebKey(web_key_urls.img_key_url); const c = new Int32Array(4); const _h = class _h { constructor() { __publicField(this, "_dataLength", 0); __publicField(this, "_bufferLength", 0); __publicField(this, "_state", new Int32Array(4)); __publicField(this, "_buffer", new ArrayBuffer(68)); __publicField(this, "_buffer8"); __publicField(this, "_buffer32"); this._buffer8 = new Uint8Array(this._buffer, 0, 68), this._buffer32 = new Uint32Array(this._buffer, 0, 17), this.start(); } static hashStr(i, a = false) { return this.onePassHasher.start().appendStr(i).end(a); } static hashAsciiStr(i, a = false) { return this.onePassHasher.start().appendAsciiStr(i).end(a); } static _hex(i) { const a = _h.hexChars, t = _h.hexOut; let e, s, r, n; for (n = 0; n < 4; n += 1) for (s = n * 8, e = i[n], r = 0; r < 8; r += 2) t[s + 1 + r] = a.charAt(e & 15), e >>>= 4, t[s + 0 + r] = a.charAt(e & 15), e >>>= 4; return t.join(""); } static _md5cycle(i, a) { let t = i[0], e = i[1], s = i[2], r = i[3]; t += (e & s | ~e & r) + a[0] - 680876936 | 0, t = (t << 7 | t >>> 25) + e | 0, r += (t & e | ~t & s) + a[1] - 389564586 | 0, r = (r << 12 | r >>> 20) + t | 0, s += (r & t | ~r & e) + a[2] + 606105819 | 0, s = (s << 17 | s >>> 15) + r | 0, e += (s & r | ~s & t) + a[3] - 1044525330 | 0, e = (e << 22 | e >>> 10) + s | 0, t += (e & s | ~e & r) + a[4] - 176418897 | 0, t = (t << 7 | t >>> 25) + e | 0, r += (t & e | ~t & s) + a[5] + 1200080426 | 0, r = (r << 12 | r >>> 20) + t | 0, s += (r & t | ~r & e) + a[6] - 1473231341 | 0, s = (s << 17 | s >>> 15) + r | 0, e += (s & r | ~s & t) + a[7] - 45705983 | 0, e = (e << 22 | e >>> 10) + s | 0, t += (e & s | ~e & r) + a[8] + 1770035416 | 0, t = (t << 7 | t >>> 25) + e | 0, r += (t & e | ~t & s) + a[9] - 1958414417 | 0, r = (r << 12 | r >>> 20) + t | 0, s += (r & t | ~r & e) + a[10] - 42063 | 0, s = (s << 17 | s >>> 15) + r | 0, e += (s & r | ~s & t) + a[11] - 1990404162 | 0, e = (e << 22 | e >>> 10) + s | 0, t += (e & s | ~e & r) + a[12] + 1804603682 | 0, t = (t << 7 | t >>> 25) + e | 0, r += (t & e | ~t & s) + a[13] - 40341101 | 0, r = (r << 12 | r >>> 20) + t | 0, s += (r & t | ~r & e) + a[14] - 1502002290 | 0, s = (s << 17 | s >>> 15) + r | 0, e += (s & r | ~s & t) + a[15] + 1236535329 | 0, e = (e << 22 | e >>> 10) + s | 0, t += (e & r | s & ~r) + a[1] - 165796510 | 0, t = (t << 5 | t >>> 27) + e | 0, r += (t & s | e & ~s) + a[6] - 1069501632 | 0, r = (r << 9 | r >>> 23) + t | 0, s += (r & e | t & ~e) + a[11] + 643717713 | 0, s = (s << 14 | s >>> 18) + r | 0, e += (s & t | r & ~t) + a[0] - 373897302 | 0, e = (e << 20 | e >>> 12) + s | 0, t += (e & r | s & ~r) + a[5] - 701558691 | 0, t = (t << 5 | t >>> 27) + e | 0, r += (t & s | e & ~s) + a[10] + 38016083 | 0, r = (r << 9 | r >>> 23) + t | 0, s += (r & e | t & ~e) + a[15] - 660478335 | 0, s = (s << 14 | s >>> 18) + r | 0, e += (s & t | r & ~t) + a[4] - 405537848 | 0, e = (e << 20 | e >>> 12) + s | 0, t += (e & r | s & ~r) + a[9] + 568446438 | 0, t = (t << 5 | t >>> 27) + e | 0, r += (t & s | e & ~s) + a[14] - 1019803690 | 0, r = (r << 9 | r >>> 23) + t | 0, s += (r & e | t & ~e) + a[3] - 187363961 | 0, s = (s << 14 | s >>> 18) + r | 0, e += (s & t | r & ~t) + a[8] + 1163531501 | 0, e = (e << 20 | e >>> 12) + s | 0, t += (e & r | s & ~r) + a[13] - 1444681467 | 0, t = (t << 5 | t >>> 27) + e | 0, r += (t & s | e & ~s) + a[2] - 51403784 | 0, r = (r << 9 | r >>> 23) + t | 0, s += (r & e | t & ~e) + a[7] + 1735328473 | 0, s = (s << 14 | s >>> 18) + r | 0, e += (s & t | r & ~t) + a[12] - 1926607734 | 0, e = (e << 20 | e >>> 12) + s | 0, t += (e ^ s ^ r) + a[5] - 378558 | 0, t = (t << 4 | t >>> 28) + e | 0, r += (t ^ e ^ s) + a[8] - 2022574463 | 0, r = (r << 11 | r >>> 21) + t | 0, s += (r ^ t ^ e) + a[11] + 1839030562 | 0, s = (s << 16 | s >>> 16) + r | 0, e += (s ^ r ^ t) + a[14] - 35309556 | 0, e = (e << 23 | e >>> 9) + s | 0, t += (e ^ s ^ r) + a[1] - 1530992060 | 0, t = (t << 4 | t >>> 28) + e | 0, r += (t ^ e ^ s) + a[4] + 1272893353 | 0, r = (r << 11 | r >>> 21) + t | 0, s += (r ^ t ^ e) + a[7] - 155497632 | 0, s = (s << 16 | s >>> 16) + r | 0, e += (s ^ r ^ t) + a[10] - 1094730640 | 0, e = (e << 23 | e >>> 9) + s | 0, t += (e ^ s ^ r) + a[13] + 681279174 | 0, t = (t << 4 | t >>> 28) + e | 0, r += (t ^ e ^ s) + a[0] - 358537222 | 0, r = (r << 11 | r >>> 21) + t | 0, s += (r ^ t ^ e) + a[3] - 722521979 | 0, s = (s << 16 | s >>> 16) + r | 0, e += (s ^ r ^ t) + a[6] + 76029189 | 0, e = (e << 23 | e >>> 9) + s | 0, t += (e ^ s ^ r) + a[9] - 640364487 | 0, t = (t << 4 | t >>> 28) + e | 0, r += (t ^ e ^ s) + a[12] - 421815835 | 0, r = (r << 11 | r >>> 21) + t | 0, s += (r ^ t ^ e) + a[15] + 530742520 | 0, s = (s << 16 | s >>> 16) + r | 0, e += (s ^ r ^ t) + a[2] - 995338651 | 0, e = (e << 23 | e >>> 9) + s | 0, t += (s ^ (e | ~r)) + a[0] - 198630844 | 0, t = (t << 6 | t >>> 26) + e | 0, r += (e ^ (t | ~s)) + a[7] + 1126891415 | 0, r = (r << 10 | r >>> 22) + t | 0, s += (t ^ (r | ~e)) + a[14] - 1416354905 | 0, s = (s << 15 | s >>> 17) + r | 0, e += (r ^ (s | ~t)) + a[5] - 57434055 | 0, e = (e << 21 | e >>> 11) + s | 0, t += (s ^ (e | ~r)) + a[12] + 1700485571 | 0, t = (t << 6 | t >>> 26) + e | 0, r += (e ^ (t | ~s)) + a[3] - 1894986606 | 0, r = (r << 10 | r >>> 22) + t | 0, s += (t ^ (r | ~e)) + a[10] - 1051523 | 0, s = (s << 15 | s >>> 17) + r | 0, e += (r ^ (s | ~t)) + a[1] - 2054922799 | 0, e = (e << 21 | e >>> 11) + s | 0, t += (s ^ (e | ~r)) + a[8] + 1873313359 | 0, t = (t << 6 | t >>> 26) + e | 0, r += (e ^ (t | ~s)) + a[15] - 30611744 | 0, r = (r << 10 | r >>> 22) + t | 0, s += (t ^ (r | ~e)) + a[6] - 1560198380 | 0, s = (s << 15 | s >>> 17) + r | 0, e += (r ^ (s | ~t)) + a[13] + 1309151649 | 0, e = (e << 21 | e >>> 11) + s | 0, t += (s ^ (e | ~r)) + a[4] - 145523070 | 0, t = (t << 6 | t >>> 26) + e | 0, r += (e ^ (t | ~s)) + a[11] - 1120210379 | 0, r = (r << 10 | r >>> 22) + t | 0, s += (t ^ (r | ~e)) + a[2] + 718787259 | 0, s = (s << 15 | s >>> 17) + r | 0, e += (r ^ (s | ~t)) + a[9] - 343485551 | 0, e = (e << 21 | e >>> 11) + s | 0, i[0] = t + i[0] | 0, i[1] = e + i[1] | 0, i[2] = s + i[2] | 0, i[3] = r + i[3] | 0; } /** * Initialise buffer to be hashed */ start() { return this._dataLength = 0, this._bufferLength = 0, this._state.set(_h.stateIdentity), this; } // Char to code point to to array conversion: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt // #Example.3A_Fixing_charCodeAt_to_handle_non-Basic-Multilingual-Plane_characters_if_their_presence_earlier_in_the_string_is_unknown /** * Append a UTF-8 string to the hash buffer * @param str String to append */ appendStr(i) { const a = this._buffer8, t = this._buffer32; let e = this._bufferLength, s, r; for (r = 0; r < i.length; r += 1) { if (s = i.charCodeAt(r), s < 128) a[e++] = s; else if (s < 2048) a[e++] = (s >>> 6) + 192, a[e++] = s & 63 | 128; else if (s < 55296 || s > 56319) a[e++] = (s >>> 12) + 224, a[e++] = s >>> 6 & 63 | 128, a[e++] = s & 63 | 128; else { if (s = (s - 55296) * 1024 + (i.charCodeAt(++r) - 56320) + 65536, s > 1114111) throw new Error( "Unicode standard supports code points up to U+10FFFF" ); a[e++] = (s >>> 18) + 240, a[e++] = s >>> 12 & 63 | 128, a[e++] = s >>> 6 & 63 | 128, a[e++] = s & 63 | 128; } e >= 64 && (this._dataLength += 64, _h._md5cycle(this._state, t), e -= 64, t[0] = t[16]); } return this._bufferLength = e, this; } /** * Append an ASCII string to the hash buffer * @param str String to append */ appendAsciiStr(i) { const a = this._buffer8, t = this._buffer32; let e = this._bufferLength, s, r = 0; for (; ; ) { for (s = Math.min(i.length - r, 64 - e); s--; ) a[e++] = i.charCodeAt(r++); if (e < 64) break; this._dataLength += 64, _h._md5cycle(this._state, t), e = 0; } return this._bufferLength = e, this; } /** * Append a byte array to the hash buffer * @param input array to append */ appendByteArray(i) { const a = this._buffer8, t = this._buffer32; let e = this._bufferLength, s, r = 0; for (; ; ) { for (s = Math.min(i.length - r, 64 - e); s--; ) a[e++] = i[r++]; if (e < 64) break; this._dataLength += 64, _h._md5cycle(this._state, t), e = 0; } return this._bufferLength = e, this; } /** * Get the state of the hash buffer */ getState() { const i = this._state; return { buffer: String.fromCharCode.apply(null, Array.from(this._buffer8)), buflen: this._bufferLength, length: this._dataLength, state: [i[0], i[1], i[2], i[3]] }; } /** * Override the current state of the hash buffer * @param state New hash buffer state */ setState(i) { const a = i.buffer, t = i.state, e = this._state; let s; for (this._dataLength = i.length, this._bufferLength = i.buflen, e[0] = t[0], e[1] = t[1], e[2] = t[2], e[3] = t[3], s = 0; s < a.length; s += 1) this._buffer8[s] = a.charCodeAt(s); } /** * Hash the current state of the hash buffer and return the result * @param raw Whether to return the value as an `Int32Array` */ end(i = false) { const a = this._bufferLength, t = this._buffer8, e = this._buffer32, s = (a >> 2) + 1; this._dataLength += a; const r = this._dataLength * 8; if (t[a] = 128, t[a + 1] = t[a + 2] = t[a + 3] = 0, e.set(_h.buffer32Identity.subarray(s), s), a > 55 && (_h._md5cycle(this._state, e), e.set(_h.buffer32Identity)), r <= 4294967295) e[14] = r; else { const n = r.toString(16).match(/(.*?)(.{0,8})$/); if (n === null) return i ? c : ""; const o = parseInt(n[2], 16), _ = parseInt(n[1], 16) || 0; e[14] = o, e[15] = _; } return _h._md5cycle(this._state, e), i ? this._state : _h._hex(this._state); } }; // Private Static Variables __publicField(_h, "stateIdentity", new Int32Array([ 1732584193, -271733879, -1732584194, 271733878 ])); __publicField(_h, "buffer32Identity", new Int32Array([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ])); __publicField(_h, "hexChars", "0123456789abcdef"); __publicField(_h, "hexOut", []); // Permanent instance is to use for one-call hashing __publicField(_h, "onePassHasher", new _h()); let h = _h; if (h.hashStr("hello") !== "5d41402abc4b2a76b9719d911017c592") throw new Error("Md5 self test failed."); const mixinKeyEncTab = [ 46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49, 33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40, 61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11, 36, 20, 34, 44, 52 ]; function getMixinKey(orig) { return mixinKeyEncTab.map((n) => orig[n]).join("").slice(0, 32); } function encWbi(params, img_key2, sub_key2) { const mixin_key = getMixinKey(img_key2 + sub_key2); const curr_time = Math.round(Date.now() / 1e3); const chr_filter = /[!'()*]/g; Object.assign(params, { wts: curr_time }); const query = Object.keys(params).sort().map((key) => { const value = params[key].toString().replace(chr_filter, ""); return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; }).join("&"); const wbi_sign = h.hashStr(query + mixin_key); return `${query}&w_rid=${wbi_sign}`; } const relationToUploader = { relation: { mid: 0, attribute: 0, mtime: 0, tag: null, special: 0 }, be_relation: { mid: 0, attribute: 0, mtime: 0, tag: null, special: 0 } }; const relationResult = toResult(relationToUploader); class Lifecycle { constructor() { __publicField(this, "lifecycleMap", { loading: [], interactive: [], complete: [] }); __publicField(this, "initialized", false); } initListener() { if (this.initialized) return; this.initialized = true; document.addEventListener("readystatechange", () => { const state = document.readyState; const callbacks = this.lifecycleMap[state]; if (callbacks == null ? void 0 : callbacks.length) { callbacks.forEach((fn) => { try { fn(); } catch (err) { console.error("[lifecycle]", err); } }); this.lifecycleMap[state] = []; } }); } /** * 注册生命周期函数 * @param state document的readystate * @param fn 对应生命周期的hook函数 */ register(state, fn) { this.initListener(); if (document.readyState === state || // 已经到此阶段 state === "interactive" && document.readyState === "complete") { fn(); } else { this.lifecycleMap[state].push(fn); } } } const lifecycle = new Lifecycle(); const onDocInteractive = (fn) => lifecycle.register("interactive", fn); async function fetchSubtitle(aid, cid) { const url = `https://api.bilibili.com/x/v2/dm/view?aid=${aid}&oid=${cid}&type=1`; return await fetch(url).then((result) => { return result.json(); }).then((result) => { result.data.subtitle.subtitles.forEach((element) => { element.subtitle_url = element.subtitle_url.replace(/^http:/, ""); }); return result.data.subtitle; }).catch(() => null); } function useSubtitle() { const subtitleCache = { current: new Promise((resolve) => { onDocInteractive(() => { const { aid, cid } = window.vd ?? {}; aid && cid ? resolve(fetchSubtitle(aid, cid)) : resolve(null); }); }) }; function setSubtitle(aid, cid) { if (aid && cid) { subtitleCache.current = fetchSubtitle(aid, cid); } else { subtitleCache.current = Promise.resolve(null); } } return { subtitleCache, setSubtitle }; } const useReply = (request) => { if (!request.url.includes("/x/v2/reply/wbi/main") && !request.url.includes("/x/v2/reply/reply")) return; request.credentials = "omit"; }; const usePlayer = () => { let isFirstRequest = true; const { subtitleCache, setSubtitle } = useSubtitle(); return (request) => { if (!request.url.includes("/x/player/wbi/v2")) return; if (request.type === "fetch") return; const payload = Object.fromEntries(new URL("https:" + request.url).searchParams.entries()); if (!isFirstRequest) setSubtitle(payload.aid, payload.cid); isFirstRequest = false; request.response = async (res) => { if (!(res == null ? void 0 : res.responseText)) return; const playerResponse = JSON.parse(res.responseText); playerResponse.data.login_mid = Math.floor(Math.random() * 1e5); playerResponse.data.level_info.current_level = 6; playerResponse.data.subtitle = await subtitleCache.current; res.responseText = JSON.stringify(playerResponse); }; }; }; const usePlayurl = (request) => { if (!request.url.includes("api.bilibili.com/x/player/wbi/playurl")) return; const qsParams = Object.fromEntries(new URLSearchParams(request.url.split(/\?|&w_rid/)[1]).entries()); Reflect.set(qsParams, "qn", 80); Reflect.set(qsParams, "try_look", 1); const query = encWbi(qsParams, img_key, sub_key); request.url = `//api.bilibili.com/x/player/wbi/playurl?${query}`; if (request.type === "fetch") return; request.response = (res) => { Object.defineProperty(window, "__playinfo__", { get() { return JSON.parse((res == null ? void 0 : res.responseText) ?? "{}"); }, configurable: true }); }; }; const useRelation = (request) => { if (!request.url.includes("/x/web-interface/relation")) return; if (request.type === "fetch") return; request.response = (res) => { res.responseText = JSON.stringify(relationResult); }; }; onRequest(useReply, usePlayer(), usePlayurl, useRelation); const mockUserInfo = { profile: { mid: 3493281916783362, name: "bilibili", sex: "保密", face: "https://i0.hdslb.com/bfs/face/0c84b9f4ad546d3f20324809d45fc439a2a8ddab.jpg", sign: "", rank: 1e4, level: 6, jointime: 0, moral: 70, silence: 0, email_status: 0, tel_status: 1, identification: 0, vip: { type: 0, status: 0, due_date: 0, vip_pay_type: 0, theme_type: 0, label: { path: "", text: "", label_theme: "", text_color: "", bg_style: 0, bg_color: "", border_color: "", use_img_label: true, img_label_uri_hans: "", img_label_uri_hant: "", img_label_uri_hans_static: "https://i0.hdslb.com/bfs/vip/d7b702ef65a976b20ed854cbd04cb9e27341bb79.png", img_label_uri_hant_static: "https://i0.hdslb.com/bfs/activity-plat/static/20220614/e369244d0b14644f5e1a06431e22a4d5/KJunwh19T5.png", label_id: 0, label_goto: null }, avatar_subscript: 0, nickname_color: "", role: 0, avatar_subscript_url: "", tv_vip_status: 0, tv_vip_pay_type: 0, tv_due_date: 0, avatar_icon: { icon_resource: {} }, ott_info: { vip_type: 0, pay_type: 0, pay_channel_id: "", status: 0, overdue_time: 0 }, super_vip: { is_super_vip: false } }, pendant: { pid: 0, name: "", image: "", expire: 0, image_enhance: "", image_enhance_frame: "", n_pid: 0 }, nameplate: { nid: 0, name: "", image: "", image_small: "", level: "", condition: "" }, official: { role: 0, title: "", desc: "", type: -1 }, birthday: 315504e3, is_tourist: 0, is_fake_account: 0, pin_prompting: 0, is_deleted: 0, in_reg_audit: 0, is_rip_user: false, profession: { id: 0, name: "", show_name: "", is_show: 0, category_one: "", realname: "", title: "", department: "", certificate_no: "", certificate_show: false }, face_nft: 0, face_nft_new: 0, is_senior_member: 0, honours: { mid: 3493281916783362, colour: { dark: "#CE8620", normal: "#F0900B" }, tags: null, is_latest_100honour: 0 }, digital_id: "", digital_type: -2, attestation: { type: 0, common_info: { title: "", prefix: "", prefix_title: "" }, splice_info: { title: "" }, icon: "", desc: "" }, expert_info: { title: "", state: 0, type: 0, desc: "" }, name_render: null, country_code: "86", handle: "" }, level_exp: { current_level: 6, current_min: 28800, current_exp: 29050, next_exp: "--" }, coins: 9999.99, following: 0, follower: 0 }; const SPACE = { USER_INFO: toResult(mockUserInfo) }; const useMyInfo = (request) => { if (!request.url.includes("x/space/v2/myinfo")) return; if (request.type === "xhr") return; request.response = (res) => { res.json = SPACE.USER_INFO; }; }; onRequest(useMyInfo); if (location.href.includes("live.bilibili.com")) { toggleIntercept(); } Object.defineProperty(window, "__playinfo__", { get: () => null, configurable: true }); document.cookie = `DedeUserID=${random(2 ** 53)}`; })();