// ==UserScript==
// @name Bilibili Evolved (Preview)
// @version 1.8.20
// @description Bilibili Evolved 的预览版, 可以抢先体验新功能.
// @author Grant Howard, Coulomb-G
// @copyright 2019, Grant Howard (https://github.com/the1812) & Coulomb-G (https://github.com/Coulomb-G)
// @license MIT
// @match *://*.bilibili.com/*
// @match *://*.bilibili.com
// @run-at document-start
// @updateURL https://github.com/the1812/Bilibili-Evolved/raw/preview/bilibili-evolved.preview.user.js
// @downloadURL https://github.com/the1812/Bilibili-Evolved/raw/preview/bilibili-evolved.preview.user.js
// @supportURL https://github.com/the1812/Bilibili-Evolved/issues
// @homepage https://github.com/the1812/Bilibili-Evolved
// @grant unsafeWindow
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_setClipboard
// @grant GM_info
// @grant GM_xmlhttpRequest
// @connect *
// @require https://code.jquery.com/jquery-3.4.0.min.js
// @require https://cdn.bootcss.com/jszip/3.1.5/jszip.min.js
// @require https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js
// @icon https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/images/logo-small.png
// @icon64 https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/images/logo.png
// ==/UserScript==
function logError (error) {
let finalMessage = error
if (typeof error === 'object' && 'stack' in error) {
if (settings.toastInternalError) {
finalMessage = `${error.message}\n${error.stack}`
} else {
finalMessage = error.message
}
}
Toast.error(finalMessage, '错误')
console.error(error)
}
function raiseEvent (element, eventName) {
const event = document.createEvent('HTMLEvents')
event.initEvent(eventName, true, true)
element.dispatchEvent(event)
}
async function loadLazyPanel (selector) {
await SpinQuery.unsafeJquery()
const panel = await SpinQuery.any(() => unsafeWindow.$(selector))
if (!panel) {
throw new Error(`Panel not found: ${selector}`)
}
panel.mouseover().mouseout()
}
async function loadDanmakuSettingsPanel () {
const style = document.createElement('style')
style.innerText = `.bilibili-player-video-danmaku-setting-wrap { display: none !important; }`
document.body.insertAdjacentElement('beforeend', style)
await loadLazyPanel('.bilibili-player-video-danmaku-setting')
setTimeout(() => style.remove(), 300)
}
function contentLoaded (callback) {
if (/complete|interactive|loaded/.test(document.readyState)) {
callback()
} else {
document.addEventListener('DOMContentLoaded', () => callback())
}
}
function fullyLoaded (callback) {
if (document.readyState === 'complete') {
callback()
} else {
unsafeWindow.addEventListener('load', () => callback())
}
}
function fixed (number, precision = 1) {
const str = number.toString()
const index = str.indexOf('.')
if (index !== -1) {
if (str.length - index > precision + 1) {
return str.substring(0, index + precision + 1)
} else {
return str
}
} else {
return str + '.0'
}
}
function isEmbeddedPlayer () {
return location.host === 'player.bilibili.com' || document.URL.startsWith('https://www.bilibili.com/html/player.html')
}
function isIframe () {
return document.body && unsafeWindow.parent.window !== unsafeWindow
}
const languageNameToCode = {
'日本語': 'ja-JP',
'English': 'en-US',
'Deutsch': 'de-DE'
}
const languageCodeToName = {
'ja-JP': '日本語',
'en-US': 'English',
'de-DE': 'Deutsch'
}
function getI18nKey () {
return settings.i18n ? languageNameToCode[settings.i18nLanguage] : 'zh-CN'
}
const dq = (selector) => document.querySelector(selector)
const dqa = (selector) => [...document.querySelectorAll(selector)]
const UserAgent = `Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0`
const EmptyImageUrl = 'data:image/svg+xml;utf-8,'
const ascendingSort = (itemProp) => {
return (a, b) => itemProp(a) - itemProp(b)
}
const descendingSort = (itemProp) => {
return (a, b) => itemProp(b) - itemProp(a)
}
const formatFileSize = (bytes, fixed = 1) => {
const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
let number = bytes
let unitIndex = 0
while (number >= 1024) {
number /= 1024
unitIndex++
}
return `${Math.round(number * (10 ** fixed)) / (10 ** fixed)}${units[unitIndex]}`
}
const formatDuration = (time, fixed = 0) => {
const second = (time % 60).toFixed(fixed)
const minute = (Math.trunc(time / 60) % 60).toString()
const hour = Math.trunc(time / 3600).toString()
if (hour === '0') {
return `${minute.padStart(2, '0')}:${second.padStart(2, '0')}`
}
return `${hour}:${minute.padStart(2, '0')}:${second.padStart(2, '0')}`
}
const getDpiSourceSet = (src, baseSize, extension = 'jpg') => {
const dpis = [1, 1.25, 1.5, 1.75, 2, 2.25, 2.5, 2.75, 3, 3.25, 3.5, 3.75, 4]
return dpis.map(dpi => {
if (typeof baseSize === 'object') {
if ('width' in baseSize && 'height' in baseSize) {
return `${src}@${Math.trunc(baseSize.width * dpi)}w_${Math.trunc(baseSize.height * dpi)}h.${extension} ${dpi}x`
} else if ('width' in baseSize) {
return `${src}@${Math.trunc(baseSize.width * dpi)}w.${extension} ${dpi}x`
} else if ('height' in baseSize) {
return `${src}@${Math.trunc(baseSize.height * dpi)}h.${extension} ${dpi}x`
}
} else {
return `${src}@${Math.trunc(baseSize * dpi)}w_${Math.trunc(baseSize * dpi)}h.${extension} ${dpi}x`
}
}).join(",")
}
const isOffline = typeof offlineData !== 'undefined'
const customNavbarDefaultOrders = {
blank1: 0,
logo: 1,
category: 2,
rankingLink: 3,
drawingLink: 4,
musicLink: 5,
gamesIframe: 6,
livesIframe: 7,
shopLink: 8,
mangaLink: 9,
blank2: 10,
search: 11,
userInfo: 12,
messages: 13,
activities: 14,
bangumi: 15,
watchlaterList: 16,
favoritesList: 17,
historyList: 18,
upload: 19,
blank3: 20,
}
const settings = {
useDarkStyle: false,
compactLayout: false,
// showBanner: true,
hideBanner: false,
expandDanmakuList: true,
expandDescription: true,
watchLaterRedirect: true,
touchNavBar: false,
touchVideoPlayer: false,
customControlBackgroundOpacity: 0.64,
customControlBackground: true,
darkScheduleStart: '18:00',
darkScheduleEnd: '6:00',
darkSchedule: false,
blurVideoControl: false,
toast: true,
fullTweetsTitle: true,
fullPageTitle: false,
removeVideoTopMask: false,
removeLiveWatermark: true,
harunaScale: true,
removeAds: true,
showBlockedAdsTip: false,
hideTopSearch: false,
touchVideoPlayerDoubleTapControl: false,
customStyleColor: '#00A0D8',
preserveRank: true,
blurBackgroundOpacity: 0.382,
useDefaultPlayerMode: false,
applyPlayerModeOnPlay: true,
defaultPlayerMode: '常规',
useDefaultVideoQuality: false,
defaultVideoQuality: '自动',
useDefaultDanmakuSettings: false,
enableDanmaku: true,
rememberDanmakuSettings: false,
danmakuSettings: {
subtitlesPreserve: false,
smartMask: false,
},
defaultPlayerLayout: '新版',
defaultBangumiLayout: '旧版',
useDefaultPlayerLayout: false,
skipChargeList: false,
comboLike: false,
autoLightOff: false,
useCache: true,
autoContinue: false,
allowJumpContinue: false,
autoPlay: false,
deadVideoTitleProvider: '稍后再看',
useBiliplusRedirect: false,
biliplusRedirect: false,
framePlayback: true,
useCommentStyle: true,
imageResolution: false,
imageResolutionScale: 'auto',
toastInternalError: false,
i18n: false,
i18nLanguage: '日本語',
playerFocus: false,
playerFocusOffset: -10,
oldTweets: false,
simplifyLiveroom: false,
simplifyLiveroomSettings: {
vip: true,
fansMedal: true,
title: true,
userLevel: true,
guard: true,
systemMessage: true,
welcomeMessage: true,
giftMessage: true,
guardPurchase: true,
popup: false,
skin: false,
},
customNavbar: true,
customNavbarFill: false,
customNavbarShadow: true,
customNavbarCompact: false,
customNavbarBlur: true,
customNavbarBlurOpacity: 0.7,
customNavbarOrder: { ...customNavbarDefaultOrders },
customNavbarHidden: [],
customNavbarBoundsPadding: 5,
playerShadow: false,
narrowDanmaku: true,
favoritesRedirect: true,
outerWatchlater: true,
hideOldEntry: true,
videoScreenshot: false,
hideBangumiReviews: false,
filenameFormat: '[title][ - ep]',
sideBarOffset: 0,
noLiveAutoplay: false,
hideHomeLive: false,
noMiniVideoAutoplay: false,
useDefaultVideoSpeed: false,
defaultVideoSpeed: '1.0',
hideCategory: false,
foldComment: true,
downloadVideoDefaultDanmaku: '无',
aria2RpcOption: {
secretKey: '',
dir: '',
host: '127.0.0.1',
port: '6800',
method: 'get',
skipByDefault: false,
maxDownloadLimit: '',
},
searchHistory: [],
seedsToCoins: true,
autoSeedsToCoins: true,
lastSeedsToCoinsDate: 0,
autoDraw: false,
keymap: false,
doubleClickFullscreen: false,
doubleClickFullscreenPreventSingleClick: false,
cache: {},
}
const fixedSettings = {
guiSettings: true,
viewCover: true,
notifyNewVersion: true,
clearCache: true,
downloadVideo: true,
downloadDanmaku: true,
downloadAudio: true,
playerLayout: true,
medalHelper: true,
about: true,
forceWide: false,
useNewStyle: false,
overrideNavBar: false,
touchVideoPlayerAnimation: false,
allNavbarFill: false,
showDeadVideoTitle: false,
latestVersionLink: 'https://github.com/the1812/Bilibili-Evolved/raw/preview/bilibili-evolved.preview.user.js',
currentVersion: GM_info.script.version,
}
const settingsChangeHandlers = {}
function addSettingsListener (key, handler, initCall) {
if (!settingsChangeHandlers[key]) {
settingsChangeHandlers[key] = [handler]
} else {
settingsChangeHandlers[key].push(handler)
}
if (initCall) {
const value = settings[key]
handler(value, value)
}
}
function removeSettingsListener (key, handler) {
const handlers = settingsChangeHandlers[key]
if (!handlers) {
return
}
handlers.splice(handlers.indexOf(handler), 1)
}
function loadSettings () {
for (const key in fixedSettings) {
settings[key] = fixedSettings[key]
GM_setValue(key, fixedSettings[key])
}
if (Object.keys(languageCodeToName).includes(navigator.language)) {
settings.i18n = true
settings.i18nLanguage = languageCodeToName[navigator.language]
}
for (const key in settings) {
let value = GM_getValue(key)
if (value === undefined) {
value = settings[key]
GM_setValue(key, settings[key])
} else if (settings[key] !== undefined && value.constructor === Object) {
value = Object.assign(settings[key], value)
}
Object.defineProperty(settings, key, {
get () {
return value
},
set (newValue) {
value = newValue
GM_setValue(key, newValue)
const handlers = settingsChangeHandlers[key]
if (handlers) {
if (key === 'useDarkStyle') {
setTimeout(() => handlers.forEach(h => h(newValue, value)), 200)
} else {
handlers.forEach(h => h(newValue, value))
}
}
const input = document.querySelector(`input[key=${key}]`)
if (input !== null) {
if (input.type === 'checkbox') {
input.checked = newValue
} else if (input.type === 'text' && !input.parentElement.classList.contains('gui-settings-dropdown')) {
input.value = newValue
}
}
}
})
}
}
function saveSettings (newSettings) {
}
function onSettingsChange () {
console.warn('此功能已弃用.')
}
class Ajax {
static send (xhr, body, text = true) {
return new Promise((resolve, reject) => {
xhr.addEventListener('load', () => {
// if (xhr.status.toString().match(/^[45]/)) {
// reject(xhr.status)
// } else {
resolve(text ? xhr.responseText : xhr.response)
// }
})
xhr.addEventListener('error', () => reject(xhr.status))
xhr.send(body)
})
}
static getBlob (url) {
const xhr = new XMLHttpRequest()
xhr.responseType = 'blob'
xhr.open('GET', url)
return this.send(xhr, undefined, false)
}
static getBlobWithCredentials (url) {
const xhr = new XMLHttpRequest()
xhr.responseType = 'blob'
xhr.open('GET', url)
xhr.withCredentials = true
return this.send(xhr, undefined, false)
}
static async getJson (url) {
return JSON.parse(await this.getText(url))
}
static async getJsonWithCredentials (url) {
return JSON.parse(await this.getTextWithCredentials(url))
}
static getText (url) {
const xhr = new XMLHttpRequest()
xhr.open('GET', url)
return this.send(xhr)
}
static getTextWithCredentials (url) {
const xhr = new XMLHttpRequest()
xhr.open('GET', url)
xhr.withCredentials = true
return this.send(xhr)
}
static postText (url, body) {
const xhr = new XMLHttpRequest()
xhr.open('POST', url)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
return this.send(xhr, body)
}
static postTextWithCredentials (url, body) {
const xhr = new XMLHttpRequest()
xhr.open('POST', url)
xhr.withCredentials = true
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
return this.send(xhr, body)
}
static postJson (url, json) {
const xhr = new XMLHttpRequest()
xhr.open('POST', url)
xhr.setRequestHeader('Content-Type', 'application/json')
return this.send(xhr, JSON.stringify(json), false)
}
static postJsonWithCredentials (url, json) {
const xhr = new XMLHttpRequest()
xhr.open('POST', url)
xhr.withCredentials = true
xhr.setRequestHeader('Content-Type', 'application/json')
return this.send(xhr, JSON.stringify(json), false)
}
static getHandlers (name) {
name = name.toLowerCase()
let handlers = Ajax[name]
if (handlers === undefined) {
handlers = Ajax[name] = []
}
return handlers
}
static addEventListener (type, handler) {
const handlers = Ajax.getHandlers(type)
handlers.push(handler)
}
static removeEventListener (type, handler) {
const handlers = Ajax.getHandlers(type)
handlers.splice(handlers.indexOf(handler), 1)
}
static monkey (details) {
return new Promise((resolve, reject) => {
const fullDetails = {
...details,
onload: r => resolve(r.response),
onerror: r => reject(r),
}
if (!('method' in fullDetails)) {
fullDetails.method = 'GET'
}
GM_xmlhttpRequest(fullDetails)
})
}
}
// https://github.com/the1812/Bilibili-Evolved/issues/84
function setupAjaxHook () {
const original = {
open: XMLHttpRequest.prototype.open,
send: XMLHttpRequest.prototype.send
}
const fireHandlers = (name, thisArg, ...args) => Ajax.getHandlers(name).forEach(it => it.call(thisArg, ...args))
const hook = (name, thisArgs, ...args) => {
fireHandlers('before' + name, thisArgs, ...args)
const returnValue = original[name].call(thisArgs, ...args)
fireHandlers('after' + name, thisArgs, ...args)
return returnValue
}
const hookOnEvent = (name, thisArg) => {
if (thisArg[name]) {
const originalHandler = thisArg[name]
thisArg[name] = (...args) => {
fireHandlers('before' + name, thisArg, ...args)
originalHandler.apply(thisArg, args)
fireHandlers('after' + name, thisArg, ...args)
}
} else {
thisArg[name] = (...args) => {
fireHandlers('before' + name, thisArg, ...args)
fireHandlers('after' + name, thisArg, ...args)
}
}
}
XMLHttpRequest.prototype.open = function (...args) { return hook('open', this, ...args) }
XMLHttpRequest.prototype.send = function (...args) {
hookOnEvent('onreadystatechange', this)
hookOnEvent('onload', this)
return hook('send', this, ...args)
}
}
function loadResources () {
Resource.root = 'https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/'
Resource.all = {}
Resource.displayNames = {}
Resource.reloadables = [
'useDarkStyle',
'hideBanner',
'customNavbar',
'playerShadow',
'narrowDanmaku',
'compactLayout',
'useCommentStyle',
'removeVideoTopMask',
'hideOldEntry',
'hideBangumiReviews',
'videoScreenshot',
'blurVideoControl',
'customControlBackground',
'harunaScale',
'removeLiveWatermark',
'framePlayback',
'hideCategory',
'fullTweetsTitle',
]
for (const [key, data] of Object.entries(Resource.manifest)) {
const resource = new Resource(data.path, { styles: data.styles, alwaysPreview: data.alwaysPreview })
resource.key = key
resource.dropdown = data.dropdown
if (data.displayNames) {
resource.displayName = data.displayNames[key]
Object.assign(Resource.displayNames, data.displayNames)
}
if (data.style) {
const styleKey = key + 'Style'
const style = Resource.all[styleKey] = new Resource(data.path.replace('.js', '.css'), { alwaysPreview: data.alwaysPreview })
style.key = styleKey
switch (data.style) {
case 'instant':
{
resource.styles.push(styleKey)
break
}
case true:
{
resource.dependencies.push(style)
break
}
case 'important':
{
resource.styles.push({
key: styleKey,
important: true
})
break
}
default:
{
if (typeof data.style === 'object') {
resource.styles.push(Object.assign({ key: styleKey }, data.style))
}
break
}
}
}
if (data.html === true) {
const htmlKey = key + 'Html'
const html = Resource.all[htmlKey] = new Resource(data.path.replace('.js', '.html'), { alwaysPreview: data.alwaysPreview })
html.key = htmlKey
resource.dependencies.push(html)
}
Resource.all[key] = resource
}
for (const [key, data] of Object.entries(Resource.manifest)) {
if (data.dependencies) {
Resource.all[key].dependencies.push(...data.dependencies.map(name => Resource.all[name]))
}
}
}
// Placeholder class for Toast
class Toast {
show () { }
dismiss () { }
static show () { }
static info () { }
static success () { }
static error () { }
}
class DoubleClickEvent {
constructor (handler, singleClickHandler = null) {
this.handler = handler
this.singleClickHandler = singleClickHandler
this.elements = []
this.clickedOnce = false
this.doubleClickHandler = e => {
if (!this.clickedOnce) {
this.clickedOnce = true
setTimeout(() => {
if (this.clickedOnce) {
this.clickedOnce = false
this.singleClickHandler && this.singleClickHandler(e)
}
}, 200)
} else {
this.clickedOnce = false
this.handler && this.handler(e)
}
}
}
bind (element) {
if (this.elements.indexOf(element) === -1) {
this.elements.push(element)
element.addEventListener('click', this.doubleClickHandler)
}
}
unbind (element) {
const index = this.elements.indexOf(element)
if (index === -1) {
return
}
this.elements.splice(index, 1)
element.removeEventListener('click', this.doubleClickHandler)
}
}
let cidHooked = false
const videoChangeCallbacks = []
class Observer {
constructor (element, callback) {
this.element = element
this.callback = callback
this.observer = null
this.options = undefined
}
start () {
if (this.element) {
this.observer = new MutationObserver(this.callback)
this.observer.observe(this.element, this.options)
}
return this
}
stop () {
this.observer && this.observer.disconnect()
return this
}
static observe (selector, callback, options) {
callback([])
let elements = selector
if (typeof selector === 'string') {
elements = [...document.querySelectorAll(selector)]
} else if (!Array.isArray(selector)) {
elements = [selector]
}
return elements.map(
it => {
const observer = new Observer(it, callback)
observer.options = options
return observer.start()
})
}
static childList (selector, callback) {
return Observer.observe(selector, callback, {
childList: true,
subtree: false,
attributes: false
})
}
static childListSubtree (selector, callback) {
return Observer.observe(selector, callback, {
childList: true,
subtree: true,
attributes: false
})
}
static attributes (selector, callback) {
return Observer.observe(selector, callback, {
childList: false,
subtree: false,
attributes: true
})
}
static attributesSubtree (selector, callback) {
return Observer.observe(selector, callback, {
childList: false,
subtree: true,
attributes: true
})
}
static all (selector, callback) {
return Observer.observe(selector, callback, {
childList: true,
subtree: true,
attributes: true
})
}
static async videoChange (callback) {
const cid = await SpinQuery.select(() => unsafeWindow.cid)
if (cid === null) {
return
}
if (!cidHooked) {
let hookedCid = cid
Object.defineProperty(unsafeWindow, 'cid', {
get () {
return hookedCid
},
set (newId) {
hookedCid = newId
if (!Array.isArray(newId)) {
videoChangeCallbacks.forEach(it => it())
}
}
})
cidHooked = true
}
// callback();
const videoContainer = await SpinQuery.select('#bofqi video')
if (videoContainer) {
Observer.childList(videoContainer, callback)
} else {
callback()
}
videoChangeCallbacks.push(callback)
}
}
class SpinQuery {
constructor (query, condition, action, failed) {
this.maxRetry = 15
this.retry = 0
this.queryInterval = 1000
this.query = query
this.condition = condition
this.action = action
this.failed = failed
}
start () {
this.tryQuery(this.query, this.condition, this.action, this.failed)
}
tryQuery (query, condition, action, failed) {
if (this.retry < this.maxRetry) {
const result = query()
if (condition(result)) {
action(result)
} else {
if (document.hasFocus()) {
this.retry++
}
setTimeout(() => this.tryQuery(query, condition, action, failed), this.queryInterval)
}
} else {
typeof failed === 'function' && failed()
}
}
static condition (query, condition, action, failed) {
if (action !== undefined) {
new SpinQuery(query, condition, action, failed).start()
} else {
return new Promise((resolve) => {
new SpinQuery(query, condition, it => resolve(it), () => resolve(null)).start()
})
}
}
static select (query, action, failed) {
if (typeof query === 'string') {
const selector = query
query = () => document.querySelector(selector)
}
return SpinQuery.condition(query, it => it !== null && it !== undefined, action, failed)
}
static any (query, action, failed) {
if (typeof query === 'string') {
const selector = query
query = () => $(selector)
}
return SpinQuery.condition(query, it => it.length > 0, action, failed)
}
static count (query, count, action, failed) {
if (typeof query === 'string') {
const selector = query
query = () => document.querySelectorAll(selector)
}
return SpinQuery.condition(query, it => it.length === count, action, failed)
}
static unsafeJquery (action, failed) {
return SpinQuery.condition(() => unsafeWindow.$, jquery => jquery !== undefined, action, failed)
}
}
class ColorProcessor {
constructor (hex) {
this.hex = hex
}
get rgb () {
return this.hexToRgb(this.hex)
}
get rgba () {
return this.hexToRgba(this.hex)
}
getHexRegex (alpha, shorthand) {
const repeat = shorthand ? '' : '{2}'
const part = `([a-f\\d]${repeat})`
const count = alpha ? 4 : 3
const pattern = `#?${part.repeat(count)}`
return new RegExp(pattern, 'ig')
}
hexToRgbOrRgba (hex, alpha) {
const isShortHand = hex.length < 6
if (isShortHand) {
const shorthandRegex = this.getHexRegex(alpha, true)
hex = hex.replace(shorthandRegex, function (...args) {
let result = ''
let i = 1
while (args[i]) {
result += args[i].repeat(2)
i++
}
return result
})
}
const regex = this.getHexRegex(alpha, false)
const regexResult = regex.exec(hex)
if (regexResult) {
const color = {
r: parseInt(regexResult[1], 16),
g: parseInt(regexResult[2], 16),
b: parseInt(regexResult[3], 16)
}
if (regexResult[4]) {
color.a = parseInt(regexResult[4], 16) / 255
}
return color
} else if (alpha) {
const rgb = this.hexToRgbOrRgba(hex, false)
if (rgb) {
rgb.a = 1
return rgb
}
}
return null
}
hexToRgb (hex) {
return this.hexToRgbOrRgba(hex, false)
}
hexToRgba (hex) {
return this.hexToRgbOrRgba(hex, true)
}
rgbToString (color) {
if (color.a) {
return `rgba(${color.r},${color.g},${color.b},${color.a})`
}
return `rgb(${color.r},${color.g},${color.b})`
}
rgbToHsb (rgb) {
const { r, g, b } = rgb
const max = Math.max(r, g, b)
const min = Math.min(r, g, b)
const delta = max - min
const s = Math.round((max === 0 ? 0 : delta / max) * 100)
const v = Math.round(max / 255 * 100)
let h
if (delta === 0) {
h = 0
} else if (r === max) {
h = (g - b) / delta % 6
} else if (g === max) {
h = (b - r) / delta + 2
} else if (b === max) {
h = (r - g) / delta + 4
}
h = Math.round(h * 60)
if (h < 0) {
h += 360
}
return { h: h, s: s, b: v }
}
get hsb () {
return this.rgbToHsb(this.rgb)
}
get grey () {
const color = this.rgb
return 1 - (0.299 * color.r + 0.587 * color.g + 0.114 * color.b) / 255
}
get foreground () {
const color = this.rgb
if (color && this.grey < 0.35) {
return '#000'
}
return '#fff'
}
makeImageFilter (originalRgb) {
const { h, s } = this.rgbToHsb(originalRgb)
const targetColor = this.hsb
const hue = targetColor.h - h
const saturate = ((targetColor.s - s) / 100 + 1) * 100
// const brightness = ((targetColor.b - b) / 100 + 1) * 100;
const filter = `hue-rotate(${hue}deg) saturate(${saturate}%)`
return filter
}
get blueImageFilter () {
const blueColor = {
r: 0,
g: 160,
b: 213
}
return this.makeImageFilter(blueColor)
}
get pinkImageFilter () {
const pinkColor = {
r: 251,
g: 113,
b: 152
}
return this.makeImageFilter(pinkColor)
}
get brightness () {
return `${this.foreground === '#000' ? '100' : '0'}%`
}
get filterInvert () {
return this.foreground === '#000' ? 'invert(0)' : 'invert(1)'
}
}
const onlineData = {};
onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/about.min.css"] = `.bilibili-evolved-about{height:100%;width:450px;background:#fff;color:#000;position:fixed;top:0;left:0;z-index:100000;transform:translateX(-100%);transition:.3s cubic-bezier(0,.86,.58,1);display:flex;flex-direction:column;box-shadow:4px 0 16px 0 #0000}body.dark .bilibili-evolved-about{background:#222;color:#eee}.bilibili-evolved-about.opened{transform:translateX(0);box-shadow:4px 0 16px 0 #0005}.about-header{padding:32px;display:flex;align-items:center;justify-content:flex-start}.about-header i{margin-right:8px;display:flex}.about-title{font-size:16pt}.about-content{padding:16px 36px 0;margin-bottom:36px;display:flex;flex-direction:column;overflow:auto}.about-content .name{font-size:24pt;display:none;align-items:center}.about-content .name svg{width:100%}body.dark .about-content .name.dark,body:not(.dark) .about-content .name.light{display:flex}.about-content .version{font-size:10pt;font-weight:700;opacity:.6;margin-top:6px;margin-bottom:6px;align-self:center}.about-content .love{font-size:10pt;margin-bottom:24px;align-self:center}.about-content .love a{color:inherit!important}.about-content section{font-size:10pt;margin-top:16px}.about-content section .title{display:flex;justify-content:center;text-transform:uppercase;font-weight:700;font-size:13pt;letter-spacing:3px;margin:8px 0 16px}.about-content section .supporter,.about-content section a{color:var(--theme-color)!important;margin-right:8px;display:inline-flex}.about-content section .supporter{user-select:none}.about-content section .supporter:not(:last-child)::after,.about-content section a:not(:last-child)::after{content:","}@keyframes spinner{to{transform:translate(-50%,-50%) rotate(360deg)}}.about-content section.participants .fetching{margin-right:8px;position:relative;display:inline-flex}.about-content section.participants .fetching::before{content:"Loading..."}`;
onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/about.min.html"] = `
`;
onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/about.min.js"] = (()=>{return(t,e)=>{(async()=>{const i=await e.importAsync("aboutHtml");document.body.insertAdjacentHTML("beforeend",i);const o=(t,e)=>t.charCodeAt(0)-e.charCodeAt(0);const n=(t,e)=>o(t.name,e.name);const s=GM_info.script.name.match(/Bilibili Evolved \((.*)\)/);const a=s?s[1]:"Stable";new Vue({el:".bilibili-evolved-about",data:{version:t.currentVersion,clientType:a,logoImage:null,logoImageDark:null,branch:null,authors:[{name:"Grant Howard",link:"https://github.com/the1812"},{name:"Coulomb-G",link:"https://github.com/Coulomb-G"}],contributors:[{name:"PleiadeSubaru",link:"https://github.com/Etherrrr"}].sort(n),fetching:true,participants:[],websites:[{name:"GitHub",link:"https://github.com/the1812/Bilibili-Evolved/"},{name:"Greasy Fork",link:"https://greasyfork.org/zh-CN/scripts/373563-bilibili-evolved"}],components:[{name:"Vue.js",link:"https://cn.vuejs.org/index.html"},{name:"JSZip",link:"https://stuk.github.io/jszip/"},{name:"jQuery",link:"http://jquery.com/"},{name:"debounce",link:"https://github.com/component/debounce/"},{name:"Slip.js",link:"https://github.com/kornelski/slip"},{name:"MDI",link:"https://materialdesignicons.com"}]},mounted(){document.querySelector(".bilibili-evolved-about").addEventListener("be:about-load",()=>{this.init()},{once:true})},methods:{async getLogos(){this.logoImage=await Ajax.getText(`https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/images/bilibili-evolved-wide.svg`);this.logoImageDark=await Ajax.getText(`https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/images/bilibili-evolved-wide-dark.svg`)},async init(){this.branch=/Preview|Local/.test(a)?"preview":"master";this.getLogos();const t=new Set;let e=[];let i=1;do{e=await Ajax.getJson(`https://api.github.com/repos/the1812/Bilibili-Evolved/issues?state=all&direction=asc&per_page=100&page=${i}`).catch(()=>{e=[{name:"电波无法到达(´・_・`)",link:null}]});i++;for(const i of e){t.add(i.user.login)}}while(e.length>0);this.participants=[...t].map(t=>{return{name:t,link:`https://github.com/${t}`}}).filter(({link:t})=>{return!this.authors.some(e=>e.link===t)&&!this.contributors.some(e=>e.link===t)}).sort(n);this.fetching=false}}})})()}})();
onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/aria2-rpc.min.js"] = (()=>{return(t,e)=>{function o(){const e=t.aria2RpcOption;const o=e.host.match(/^http[s]?:\/\//)?e.host:"http://"+e.host;const r="aria2.addUri";return{option:e,host:o,methodName:r}}async function r(t,e=false){try{let o=await t();if(typeof o==="string"){o=JSON.parse(o)}if(o.error!==undefined){if(o.error.code===1){logError(`请求遭到拒绝, 请检查您的密钥相关设置.`)}else{logError(`请求发生错误, code = ${o.error.code}, message = ${o.error.message}`)}return false}if(!e){Toast.success(`成功发送了请求, GID = ${o.result}`,"aria2 RPC",5e3)}return true}catch(t){logError(`无法连接到RPC主机.`);return false}}async function s(t,e=false){const{option:s,host:n,methodName:a}=o();return await r(async()=>{const e=window.btoa(unescape(encodeURIComponent(JSON.stringify(t.params))));const o=`${n}:${s.port}/jsonrpc?method=${a}&id=${t.id}¶ms=${e}`;console.log(`RPC request:`,o);if(o.startsWith("http:")){return await new Promise((t,e)=>{GM_xmlhttpRequest({method:"GET",url:o,responseType:"json",onload:e=>t(e.response),onerror:t=>e(t)})})}else{return await Ajax.getJson(o)}},e)}async function n(t,e=false){const{option:s,host:n,methodName:a}=o();return await r(async()=>{const e=`${n}:${s.port}/jsonrpc`;const o={method:a,id:t.id,params:t.params};if(e.startsWith("http:")){return await new Promise((t,r)=>{GM_xmlhttpRequest({method:"POST",url:e,responseType:"json",data:JSON.stringify(o),onload:e=>t(e.response),onerror:t=>r(t)})})}else{return await Ajax.postJson(e,o)}},e)}async function a(e,o=false){const r=t.aria2RpcOption;for(const t of e){let e;if(r.method==="get"){e=await s(t,o)}else{e=await n(t,o)}if(o===true&&e===false){logError(`${decodeURIComponent(t.id)} 导出失败`)}}}return{export:{sendRpc:a}}}})();
onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/auto-continue.min.js"] = (()=>{return(e,i)=>{if(typeof isEmbeddedPlayer!=="undefined"&&isEmbeddedPlayer()){return}function t(i){const t=i.text();if(/第(\d+)话/.test(t)){if(e.allowJumpContinue){i.parent().find(".bilibili-player-video-toast-item-jump").click()}return}const n=/((\d)*:)?(\d)*:(\d)*/g;const r=t.match(n);if(!r){return}const o=r[0].split(":");const l=(()=>{if(o.length===3){const[e,i,t]=o.map(e=>parseInt(e));return e*60*60+i*60+t}else if(o.length===2){const[e,i]=o.map(e=>parseInt(e));return e*60+i}else{logError(`解析历史时间发生错误: historyTime=${JSON.stringify(o)}`);return NaN}})();const s=i.parent();const a=document.querySelector("video");if(l从头开始`);e.appendTo(s).on("click",()=>{a.currentTime=0;s.find(".bilibili-player-video-toast-item-close").get(0).click()});i.html(`已跳转到上次历史记录${r[0]}`)}else{s.find(".bilibili-player-video-toast-item-close").get(0).click()}}function n(){SpinQuery.condition(()=>$(".bilibili-player-video-toast-item-text"),e=>e.text().indexOf("上次看到")!==-1,e=>t(e.filter((e,i)=>i.innerText.indexOf("上次看到")!==-1)))}Observer.videoChange(n)}})();
onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/auto-draw.min.js"] = (()=>{return(t,n)=>{(async()=>{if(!/^https:\/\/live\.bilibili\.com\/[\d]+/.test(document.URL)){return}const t=await SpinQuery.condition(()=>dq(".chat-popups-section"),t=>t.querySelector("chat-draw-area")===null);if(!t){console.warn("[自动领奖] 未能找到弹窗容器");return}Observer.childListSubtree(t,()=>{let t;console.log("draw button = ",dq(".chat-popups-section .draw>span:nth-child(3)"));t=dq(".chat-popups-section .draw>span:nth-child(3)");if(t===null){const t=dq(".chat-popups-section .function-bar>span:nth-child(3)");if(t!==null){const n=Observer.attributes(t,()=>{if(t.style.display!=="none"){n.forEach(t=>t.stop());t.click()}})}}if(t!==null){t.click()}})})()}})();
onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/auto-play.min.js"] = (()=>{return(e,d)=>{if(typeof isEmbeddedPlayer!=="undefined"&&isEmbeddedPlayer()){return}SpinQuery.condition(()=>document.querySelector(".bilibili-player-video video"),e=>e&&e.paused===true,e=>e.play())}})();
onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/batch-download.min.js"] = (()=>{return(t,e)=>{const i=12;class r{constructor(){this.itemList=[];this.itemFilter=(()=>true)}async getItemList(){}async collectData(){}async collectAria2(r,s){const n=JSON.parse(await this.collectData(r));if(s){const r=t.aria2RpcOption;const{sendRpc:s}=await e.importAsync("aria2-rpc");for(const t of n){const e=t.fragments.map((e,s)=>{let n="";if(t.fragments.length>1){n=" - "+(s+1)}const a=[];if(r.secretKey!==""){a.push(`token:${r.secretKey}`)}a.push([e.url]);a.push({referer:document.URL.replace(window.location.search,""),"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0",out:`${t.title}${n}.flv`,split:i,dir:r.dir||undefined,"max-download-limit":r.maxDownloadLimit||undefined});const o=encodeURIComponent(`${t.title}${n}`);return{params:a,id:o}});await s(e,true)}}else{return`\n# Generated by Bilibili Evolved Video Export\n# https://github.com/the1812/Bilibili-Evolved/\n${n.map(t=>{return t.fragments.map(e=>{return`\n${e.url}\n referer=${t.referer}\n user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0\n out=${t.title}.flv\n split=${i}\n `.trim()})}).join("\n")}\n `.trim()}}}class s extends r{static async test(){if(!document.URL.includes("/www.bilibili.com/video/av")){return false}return await SpinQuery.select("#multi_page")!==null}async getItemList(){if(this.itemList.length>0){return this.itemList}const t=`https://api.bilibili.com/x/web-interface/view?aid=${unsafeWindow.aid}`;const e=await Ajax.getJson(t);if(e.code!==0){Toast.error(`获取视频选集列表失败, message=${e.message}`,"批量下载");return""}const i=e.data.pages;if(i===undefined){Toast.error(`获取视频选集列表失败, 没有找到选集信息.`,"批量下载");return""}this.itemList=i.map(t=>{return{title:`P${t.page} ${t.part}`,cid:t.cid,aid:unsafeWindow.aid}});return this.itemList}async collectData(t){const e=[];for(const i of(await this.getItemList()).filter(this.itemFilter)){const r=`https://api.bilibili.com/x/player/playurl?avid=${i.aid}&cid=${i.cid}&qn=${t}&otype=json`;const s=await Ajax.getJsonWithCredentials(r);const n=s.data||s.result||s;if(n.quality!==t){console.warn(`${i.title} 不支持所选画质, 已回退到较低画质. (quality=${n.quality})`)}const a=n.durl.map(t=>{return{length:t.length,size:t.size,url:t.url}});e.push({fragments:a,title:i.title,totalSize:a.map(t=>t.size).reduce((t,e)=>t+e),cid:i.cid,referer:document.URL.replace(window.location.search,"")})}return JSON.stringify(e)}}class n extends r{static async test(){return document.URL.includes("/www.bilibili.com/bangumi")}async getItemList(){if(this.itemList.length>0){return this.itemList}const t=document.querySelector("meta[property='og:url']");if(t===null){Toast.error("获取番剧数据失败: 无法找到 Season ID","批量下载");return""}const e=t.getAttribute("content").match(/play\/ss(\d+)/)[1];if(e===undefined){Toast.error("获取番剧数据失败: 无法解析 Season ID","批量下载");return""}const i=await Ajax.getJson(`https://api.bilibili.com/pgc/web/season/section?season_id=${e}`);if(i.code!==0){Toast.error(`获取番剧数据失败: 无法获取番剧集数列表, message=${i.message}`,"批量下载");return""}this.itemList=i.result.main_section.episodes.map((t,e)=>{return{aid:t.aid,cid:t.cid,title:t.long_title?`${t.title} - ${t.long_title}`:`${e+1} - ${t.title}`}});return this.itemList}async collectData(t){const e=[];for(const i of(await this.getItemList()).filter(this.itemFilter)){const r=`https://api.bilibili.com/pgc/player/web/playurl?avid=${i.aid}&cid=${i.cid}&qn=${t}&otype=json`;const s=await Ajax.getJsonWithCredentials(r);const n=s.data||s.result||s;if(n.quality!==t){console.warn(`${i.title} 不支持所选画质, 已回退到较低画质. (quality=${n.quality})`)}const a=n.durl.map(t=>{return{length:t.length,size:t.size,url:t.url}});e.push({fragments:a,title:i.title,totalSize:a.map(t=>t.size).reduce((t,e)=>t+e),cid:i.cid,referer:document.URL.replace(window.location.search,"")})}return JSON.stringify(e)}}const a=[n,s];let o=null;class l{constructor(){this.itemFilter=(()=>true)}static async test(){for(const t of a){if(await t.test()===true){o=t;return true}}o=null;return false}getExtractor(){if(o===null){logError("[批量下载] 未找到合适的解析模块.");throw new Error(`[Batch Download] module not found.`)}const t=new o;t.itemFilter=this.itemFilter;return t}async getItemList(){const t=this.getExtractor();return await t.getItemList()}async collectData(t,e){const i=this.getExtractor();const r=await i.collectData(t.quality);e.dismiss();return r}async collectAria2(t,e,i){const r=this.getExtractor();const s=await r.collectAria2(t.quality,i);e.dismiss();return s}}return{export:{BatchExtractor:l}}}})();
onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/biliplus-redirect.min.js"] = (()=>{return(i,e)=>{const n=`hd.biliplus.com`;const c=["bilibili.com/video/av","bilibili.com/bangumi/play","bilibili.com/bangumi/media","space.bilibili.com"];return{widget:{condition:()=>{return c.some(i=>document.URL.includes(i))},content:`\n `,success:()=>{const i=document.querySelector("#biliplus-redirect");i.addEventListener("click",()=>{if(location.host==="space.bilibili.com"){location.assign(document.URL.replace("space.bilibili.com/",`${n}/space/`))}else if(document.URL.includes("/bangumi/")){const i=unsafeWindow.aid||document.querySelector(".av-link,.info-sec-av").innerText.replace(/[aAvV]/g,"");location.assign(`https://${n}/video/av${i}/`)}else{location.host=n}})}}}}})();
onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/blur-video-control.min.css"] = `.video-control-blur-layer{width:100%;height:100%;position:absolute;-webkit-backdrop-filter:blur(48px);backdrop-filter:blur(48px);z-index:-1;top:0}.bilibili-player-video-control-mask{background:0 0!important}.bilibili-player-video-control-bottom,.bui-slider .bui-track.bui-track-video-progress .bui-bar-wrap{background-color:transparent!important}.bilibili-player-video-control-bottom{position:relative}.bilibili-player-area .bilibili-player-video-control-bottom,.bilibili-player-area .bilibili-player-video-control-wrap{transition:none!important}`;
onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/blur-video-control.min.js"] = (()=>{return(o,e)=>{const l=async()=>{const o=await SpinQuery.count(".bui-slider .bui-track.bui-track-video-progress,.bilibili-player-video-control-bottom",2);o.forEach(o=>{if(!o.classList.contains("video-control-blur-container")){o.classList.add("video-control-blur-container");o.insertAdjacentHTML("afterbegin",``)}})};e.applyStyle("blurVideoControlStyle");Observer.videoChange(l);return{reload:()=>{document.querySelectorAll(".video-control-blur-layer").forEach(o=>o.style.display="block");e.applyStyle("blurVideoControlStyle")},unload:()=>{document.querySelectorAll(".video-control-blur-layer").forEach(o=>o.style.display="none");e.removeStyle("blurVideoControlStyle")}}}})();
onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/bundle.json"] = `{
"about.min.css": "839FB8FA5429AFB22AAE52B0B1114EB5474333D12082554BAD790E75936CF48C",
"about.min.html": "AE18D23499F4B636B32267440FAE92D67700FCA2F2AA2FBB4E2692018D66DD5F",
"about.min.js": "0E79611FC34B3EFB4B9428A18C391DF59674D5C41D34023F6F9DEFB656882A9E",
"aria2-rpc.min.js": "B13E731DDD503A645A19BB243FF0148BEAC313F0A54454752A07387176F04046",
"auto-continue.min.js": "96CD47C367D7397CE1467A69764409BAEFF16E8F535BC8E15523CD0B8A86687E",
"auto-draw.min.js": "AE72CF2623DF2D15AD4AF82D125FFAF7EF5B1E6B36D9E9AC646AC98AA6AA8698",
"auto-play.min.js": "DC9938AC15DADDC9D88DCA0C9BE64BE142C37D32CB85E42E23DAB2A7378531E5",
"batch-download.min.js": "530C04A19539496385F033F01AFDB1291F96F63E396D938F277901A9D74A3B13",
"biliplus-redirect.min.js": "B40E8AD06B180C2E8CCC4C67D17907D2FE6388EC1F1B1E2DDAF80B3F517B3C60",
"blur-video-control.min.css": "B72FA7AD198ED1C9A9620A83881441F96F9FF3083ED12203A324B9753A7CCFFD",
"blur-video-control.min.js": "00A2AC837FC455DF2AED7D0C350265C7438CC6F5C203F085E19639DDB86D0E11",
"clear-cache.min.js": "B25E550E96C9F991E3DCD0D6D81A95B913F029C5651F5FB3CDFB18CC7CB8F6F4",
"combo-like.min.js": "239FC1F3AC50C9BBF3788E9C3ECADEEB0CA0F435D1EA7AD4A4AB471C8549A0C2",
"comment-dark.min.css": "E980508E86203743C36FEE4F7149BFF53961ECBC4EC140E8C162D18D395B940A",
"comment.min.css": "CEDA2E6733E294A608812309FA6629045ABBC55A55C7677B6B60F019C0B62CAB",
"comment.min.js": "64F7B6951861C25799C48BB1ABCF2A73F79BCBBFC1E9D3BD45EC1F16F94F6451",
"compact-layout.min.css": "CAC8B0DBA8E90B38D31F0811B7B469709052204AC36D5D3F20FE5D0899FDDCCB",
"compact-layout.min.js": "B20609A7CBBDB1845FA0156FB5BE6B1E1A1B8B069EA85F65D16241DD2C12D738",
"custom-control-background.min.css": "1981FD2BF3B17ECF33F98D5DEDAF0D32ACBE9532A51FDB70822286991AB98EF3",
"custom-control-background.min.js": "6B6B7E99E88E9242AB4AB3A0B108AADBF48BD43D6A8F11F0E281F476A7D84C47",
"custom-navbar.min.css": "0C4E62C1C1C5B219F3EDCBDB14FB20BFC8BAEBAB5111E944B0345BC0C15561D4",
"custom-navbar.min.html": "72A66BCE1D82163555AFBEAC651A0BB42A661338878C55B9BE8CE3655767A3CC",
"custom-navbar.min.js": "A093FF5B061E83E21474D78490A53B06FE6B11F6D2E85AF33826E4700F767FFE",
"danmaku-converter.min.js": "E056FD0E80469D3EC4C11BDD78435A1EBFA319DA8DAD9063286E1CA50037EA94",
"dark-important.min.css": "FED04F62558B979ACADEBC3850DF1155CEF55F99AAF6130CB9CFF741DCA16F92",
"dark-navbar.min.css": "C02A4001942DE8E26C61520C2499D80512D8CBA0BBA81E7065BA219C4DF9C11D",
"dark-schedule.min.js": "853C446547603F4F0425F19F09F73335C9EC451A790C1C07E5E5B88A09E9B453",
"dark-styles.min.js": "A6CFEC32B3F78FD2BD5DBB2347A517F9A633802098DF458F70CBE094F9CAD854",
"dark.min.css": "FA9F1050D5C4AD32C45977163E8BC0F492717415F0C448E81C731FFDBE82114B",
"debounce.min.js": "54D33E1273C1F3FE19550BF1844339C3D54D6B01DF8A39C3162D95B93B079CFA",
"default-danmaku-settings.min.css": "D9942B184FEDA7B08CFA0C34920E97D7A83B81762DCBF757642EBB60F95FF25D",
"default-danmaku-settings.min.js": "30A8D36137B5A4D560BD47F7A264F77C7DD4428291DF3E7EBD8D632B2AE9973E",
"default-player-layout.min.js": "F3EF04CD6095D068F0E21DA99D546AB1C97AEE73B8D9E1DCD7ADCAD4776C9C84",
"default-player-mode.min.js": "6A699382CE6C036B1510DB53AD21D4E98472140E8470BD38BD94B4D249C57FF2",
"default-video-quality.min.js": "D423D80B3151ACA49D8F769054E0F839DA2367E7F7C0590EFD60F71B4A6BEADB",
"default-video-speed.min.js": "34E3D2BC8BD5BBC2534EDE6D7B02DE6D5F4A01879641A9E128B4C24124759D77",
"double-click-fullscreen.min.js": "09C035FC7E281ABB042A4200F69757AB093079DBCC9939BE8C53C23EE2EDE41C",
"download-audio.min.js": "DD226915B2B9A2368CF2B9E0AA9EA367C1A21ADA9A378C225E78DE1D4C60C9A7",
"download-danmaku.min.js": "8A39F93E266A7BE09091D06EF3CC40803CD2F813AEDD1EC3C822D64151770D6E",
"download-video.min.css": "544D7CA625C22BA021D3F3629E129253E7A9BF97C51C590987C3A18DB0597CC2",
"download-video.min.html": "DA50CED55A3DF543AFC3048EBD73C9C27664BDAA637614E6C7F318E9B201ABFC",
"download-video.min.js": "BCC3A0C78C819A51A0EEE15139EFC7D950A2F193D54DE6DDCE20263F74842003",
"expand-danmaku.min.js": "B21658C40085AEA8DC49652AE62EB8610BB2EBEAF7A9C9AF69EF3B11E08EEC8D",
"expand-description.min.css": "58C7710A50521B80F7D872BDC4C652610D84C4FABC6874BA66DA37B4F8759224",
"expand-description.min.js": "A56857AD6B1C9F431B233D188E857D30DD5A2EB644986DE32A21280B1B7BC7A7",
"favorites-redirect.min.js": "70D6ECCE0402AA76387D2A3288C1148C60CC88D5378B7A2BDC813F3F78E4EE84",
"fix-fullscreen.min.js": "C0628A7CABB4421FCBD7663700EF9965C96F6D79979B9F7523A9F9B0B009C8B6",
"fold-comment.min.css": "74DF4566EB80AD7078E65E8B68633E05FC41D3B4E47A20D6E415E8A743F35378",
"fold-comment.min.js": "B149A9A8EA03DCB39BC4FF59591BE9D8E7BA45B2049A545F9611251EBE85FEA9",
"frame-playback.min.css": "07231E8699FA0542C1FD36BE278E2201016AA30C91E9EAC116B2D074B20BFCD7",
"frame-playback.min.html": "4089BD1D954155EA91D39C33E22D7585A87C3F8A9B4A6BA4CE5D97B51763C971",
"frame-playback.min.js": "57B34757FD03B9164B27DB48A1D6F4E3633086C27CD1E3246FCEDDCD7768F05E",
"full-page-title.min.css": "C4E50EBCFEDD0050DDAFFC7A9568625E417DF46F3A312CFF6CD6734B2B038D56",
"full-page-title.min.js": "D761A0C4A8B0A25CC0A23A10C495C2A5E6028BC19C6460C8ABB8D4B0B855E748",
"full-tweets-title.min.css": "13A0CF1C96F374CED3FA59A532E28B4B620D7A4C374385A363F32AD1A7656764",
"full-tweets-title.min.js": "DD57BB732ABEF7739CA84AEFF97E86F8984FCC4A8A75B957213622350B2A7C37",
"gui-settings.min.css": "9C7CABF974C76DCFAD6DBECAD8CCA7C1EFA1EAEA9977DF5F0013B3F4FA664FCD",
"gui-settings.min.html": "AA990C3CE45A68755AA9BED58AC4B13CAFC88C81FEF7C080DFB40A248D269F46",
"gui-settings.min.js": "839ED051829AE71DAD3BCD71B92365E651FF0E3B38F4719214F586E2334EC7A6",
"haruna-scale.min.js": "7B0F89A664B6A3D0BE21F7501660058DE3DC0881A81FCDA44B9F3C31BBD73D30",
"hide-bangumi-reviews.min.js": "CC3CE6B3F1606F8AB0A4ADAD3B16E6DA9245D0676ACF74B97FB143FBFF0C7223",
"hide-banner.min.css": "FF157AF84741AF0564FE2930CC49F524F99A41739DB4C44DC944EC6F4F620A0F",
"hide-banner.min.js": "465C175B25E19BC69A8CCD6DEA73447B290692BA4798D4D1B84DEF7261A921C4",
"hide-category.min.js": "64125DCFE1F7DB269049CB839B52E38B4E2D574E7A1AF6A5439BF0B77EB93EC1",
"hide-old-entry.min.js": "82C5BB63906A244E1A8CAF2162F502A31188E8437387829B4AC9950E8836100E",
"hide-top-search.min.js": "19641CCB6A883DB5DD143A768606DEF0C571572D91CCD3FD5A9302A2A916E19B",
"i18n.de-DE.min.js": "5BDAC5F0493F447A98B4D308817B21AB2787BEF9E3929EA37F0D2ACD3D879337",
"i18n.en-US.min.js": "3881C855B9044CF350A66CA56E3C42A5CEAC32FF75C563450BBF3BFA60E446AC",
"i18n.ja-JP.min.js": "25223C09901B9584DE6AEA05C3236DB24F114C69A441355B104512806AEDF394",
"i18n.min.css": "B397A0DE9F07161C909C982DCF229968BC3AADBFB4DF18C5143668FAC4D1931E",
"i18n.min.js": "7FCB933FD43C05A152B672D4BD721F3ECEBA6AD29648379947DAAFC403907B38",
"i18n.zh-TW.min.js": "803F67270809E3258E2B302ADE542B12EF222C83EDC67FB8C68301C5F4E3A1CC",
"icons.min.css": "CE45E84BCB125A434F3DE11F992BED59D39643B4A7314705809B285732615994",
"image-resolution.min.js": "0D9679DD7D7CF2709368FC4811F03CC0379EE7286432B98DB7AAB45227D20C76",
"image-viewer.min.css": "219E206912EC6FCB0E9F0EC447D19073272A959F66A782D9DF55522FD8A488B5",
"image-viewer.min.html": "763742E79923A7918F281AEBB3CEE76FE2A0AE94CACE325AE4BEE1AED451DAEA",
"index.min.html": "94B83D9EBB9005C1286A7E0759A7683932F8DADA20D07E5E9D8FF867B04D4B95",
"keymap.min.js": "A8EE3D74A3B47DFEE2842B8719DBB13FC7A2E6A5C268E42A606642B1EC036887",
"magic-grid.min.js": "83C4A66DE2E0EB3C4335241E4105AD0A95906F7B5EA129B4CD80E9985D2E09B4",
"mdi.min.js": "8A22F2F37F88F74FC07CE2FECA7CE135182058BE24409BAF3DEF0D5845B0BE1A",
"medal-helper.min.css": "205A02CC6E8B2DBDA222A0660D83EA6E4B24F0B5A753E269FED099AB8AE31B6C",
"medal-helper.min.html": "5D7057259368BE97DED3375DD904695B245AA2BF338C5E18CB3CF61DD913617C",
"medal-helper.min.js": "33751914C5DE205D79E059F7BF285E325E4D6DBFC68AE7E4D4B6307672F23B6E",
"narrow-danmaku.min.js": "12475431A527EFF15100AF57C9C53D0603BC27723126D966CB01240917602253",
"new-styles.min.js": "3D7E8E25C5B5B6BD3F784BC05D403C35F0658E67197F878874A9554C2FF5127B",
"no-banner.min.css": "DA096F94E7FA26992F3F71245E704D69A1C222D0ADA6F1990FA5D948507CE15F",
"no-live-autoplay.min.js": "EE4E05A1A2BCB96EA50C2F3891AC3EBBE65D2660103A244DB0297CC5F05D9BAE",
"no-mini-video-autoplay.min.js": "13B755C0EE0CA018AE65251E168BAF3395FEA2EB4FAD6949AADD752F61B8819B",
"notify-new-version.min.js": "60147C013AF149F726321636997E2FEBC947C151C44E73127463B88D53BCB0DD",
"old-tweets.min.js": "CF1E860AEA12A798884DE63BC8FAE1FEF84FEE526C3F896CA3D37D3B55AE84A6",
"old.min.css": "4C8C918BEBE59E9EE19D5E383234767EE2A2F1DB72E86F0C9F9CE01F26DD193C",
"outer-watchlater.min.css": "B40E94BADA1A9BC96422777B33150780330763098B539921DA05F9D3BA487424",
"outer-watchlater.min.js": "ACC9CC9A95B70FA65E5E944F996A7E586C9D6F033C50B687376505E9E308430E",
"override-navbar.min.css": "E5AA612841281169CA367A238FB934F807900A385CE2298B7352FF3CA4623757",
"override-navbar.min.js": "5EC6A7D1D2ADE38FEA0BDE3FBBDB5A4054A05FE2FC386FB3339CD9AD3AF7F4DE",
"player-focus.min.js": "2C849315D6FE5968908ACC2F0CD6252C8D5988485B10C1FD09C96D2E397FD30D",
"player-shadow.min.js": "918D2127907BC2C164CB86BF7F9C2501CF3B9CD236FEEDE5155B9B5D932F3415",
"remove-promotions.min.css": "FC6AA1EE75AFD8C82E8AFBC68FD898364AD8EB3720503B1A7A613CAB2B38C5EC",
"remove-promotions.min.js": "A10C64F78511BC75B9BBA2DFFEBF7FCC4C6C505EF2F75DC0C7AFEF3E162BEA1E",
"remove-top-mask.min.js": "A15C1EC10D2E1A61845B1ADAE51860553F96427059E10443B1E53FAF48F45304",
"remove-watermark.min.js": "EF8A48E379DE9400E7FCEA7A455EC966B56ADCE31D722FF02C8111FB92A148AF",
"screenshot.min.css": "C8BFD4B0A76A758477B767338ABA1D0A49408EDBA861351EA5CB57070515CE76",
"screenshot.min.js": "DF1F34103A1DB88A7A4F6DDAA3C8F55710FC6C11802CED917A026D66A9F7FE3B",
"scrollbar.min.css": "9792340121B6EE6E618A3F62AABD9C992D9C325803DF4879C8A74F02DA0E2213",
"seeds-to-coins.min.js": "3F1D383501A6E989255808A82850903EB10931CBE0ADE652AADED69FB9502C57",
"settings-search.min.js": "C3B605AF2581F562415B6AA30F7B1D825A74EB0B2B83A5F17A303B7B5646E261",
"settings-side-bar.min.js": "CC0E3477BF8574606720D3261C4A0202713E42B30CFE737403E629CBA97B2A98",
"settings-tooltip.en-US.min.js": "7831F2DA3138E8E4555347A7F5060D968A1D06DD239D5146217B30A08553C468",
"settings-tooltip.ja-JP.min.js": "F4158BB45CCD40EEEF9C0B9900C5A8D0C70B6EEB5F862F9CE1B77545CD07DE14",
"settings-tooltip.loader.min.js": "F9DFB09E32B8C814A61EE7E7D354C15A6FEF39BBBC22F476A930526DC26DA558",
"settings-tooltip.min.css": "0C138D5CF16B9068E73D173D229B2B458C15F50272DA73D6A580921C5A848845",
"settings-tooltip.min.js": "E9ABA72B3C29CA850342109E57B055B193F3356DD59876B202E8E908AE6247C9",
"settings-tooltip.zh-CN.min.js": "1D5476BD30DDA2930A2CEA032348FCCBC1B2EC6BED599AD1E26A63C9DDE59DD5",
"show-dead-video-title.min.js": "945C4F0E5FB2C62DB21C42FCE01829BAE7B13F4FBD90731CB85C38B82801B1A8",
"simplify-liveroom.min.css": "0F24C08B156121AF7B321448572996B29519881CC08D2EAA340BE2510E90B458",
"simplify-liveroom.min.js": "68750BB42318229348198961E88AC92E4F8D4F2AF9A8CAEFF4C6F228FC037AE6",
"skip-charge-list.min.css": "D3C988CE131CEBFAC8A60360529C83EC4AE1B9EA122F9A6924F19963E25A4FE9",
"skip-charge-list.min.js": "D057258F8EE77D949147174585B1A8C640DDB74E0C0B711A50AEAC8D6792F49F",
"slip.min.js": "0905C7F3B0BFA6535D48CA9A4D2DDCE0EDD83E66AA3D19AA3C1A6A53ECDD15FE",
"style.min.css": "27223BD1ABBB5D8E529B13C009B5099F53F75B26AA713E4C660C205C1121495B",
"text-validate.min.js": "3F523485A3EAB6F5BB5C81570A8F4796F13EA00E4A229CFD24CB10DC5B5B61C0",
"theme-colors.min.js": "3001D5DAD0EFBAEC7F96C51FD3BE2C4677E358AD70D8DD019D2280EA450A34E7",
"title.min.js": "0F738220A30AB7707BD1F7EA0380279E55295DDE500D313E8AC39EF713385B2C",
"toast.min.css": "6F4343B67FF70C0A1217051F92BC854EE7A510A5AD5F115D98203C61C5A57D27",
"toast.min.js": "F363B62C0C53F6CE5C13A186055EA40C0BC3E73A5FFD11586DDB4A17335CC930",
"touch-navbar.min.js": "21EF203296CF795E2471D04E7C44F5FA734FC7EB3EF6187B5AC6D562572D2649",
"touch-player.min.css": "70F9BB443A8D1D629EF30BEDD48BC766C2F6640CBA7C6C35B6B002FCD8BF2A66",
"touch-player.min.js": "28F2AF5C066CC4C3A2490D844861188907D1BB7B254F4B8A403F0AB3C7F4FB31",
"tweets.min.css": "9015C1F165C91B9205ABBE4E8A3B5FA83DB1EB4B5CF2442846AF61E44FF178A8",
"v-checkbox.vue.min.js": "A23C35D5627009A29FD396A024442A19E37DEE70674BF3CE0FA377D781ED2231",
"v-dropdown.vue.min.js": "66C883695F6653412980050A23F7581557407A2859214BF0CAAEC7001D0B5DDB",
"video-info.min.js": "7234A74CA28A772A31E41BBD4925FC2B22C6701419ADFD511402C6A9D6D9E5FA",
"video-story.min.js": "F9D4D2D80997DF5F11BF0CFA4D389B77BDBF1566EA6002E47174B68B440F3C0D",
"view-cover.min.js": "C458AD430FB767111D2F8E1F63BF85C3047FC7FDDED82D00C0D8EEA9542BD945",
"watchlater-api.min.js": "33466718EEB3796E3330F85BA16624428F7BBFC1D7B293A6F431373BED7773CE",
"watchlater.min.js": "B74FB2BE4B9B416C09FF8C2BABD36CB5971A4382C4143495065E94DEA1D5CBF9"
}`;
onlineData["https://raw.githubusercontent.com/the1812/Bilibili-Evolved/preview/min/bundle.zip"] = `PK ���N���� =
about.min.css�U�r� �5��X3�Q�8͠�~@?��H�$�;�{A�]ۑ������nw�C��J���Q[��þY7���!�����./x�Z;�i��K��c�Y���x��hV���eY����z'R��|12�e�?�~-H,��kc"��I��$�Kp�lI_��t�|Ls!�U|�*�<>���ag�յ:/̎���ƞ�.ɒ����f�=ܽ&tF�K����� 3[���A���SD�r�� �[.��5[���Wl���&������ߝGY�Ii�P�G���}U�6Ό�=�j��
��V����j������n�I�&[kr}�ď�;S9���ٕ��zW��u������s�uւ+���^ Y$
0l'>��,ol�cS���L�
n9q�i�݂l�2̤%�g�Pj%5�)}��w>� V�V�����Lq��D��>c3��?����������o��a��-� ��ai�ƙ�s&�N3ة
��,�
���V���?^c���PIn�?4�)�X?�����x�QJ� PK ȥOC�Z