Greasy Fork is available in English.

Bilibili 旧播放页

恢复Bilibili旧版页面,为了那些念旧的人。

От 08.12.2021. Виж последната версия.

// ==UserScript==
// @name         Bilibili 旧播放页
// @namespace    MotooriKashin
// @version      6.1.8
// @description  恢复Bilibili旧版页面,为了那些念旧的人。
// @author       MotooriKashin,wly5556
// @homepage     https://github.com/MotooriKashin/Bilibili-Old
// @supportURL   https://github.com/MotooriKashin/Bilibili-Old/issues
// @icon         https://static.hdslb.com/images/favicon.ico
// @match        *://*.bilibili.com/*
// @connect      *
// @grant        GM_xmlhttpRequest
// @grant        GM_getResourceText
// @grant        GM_getResourceURL
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_deleteValue
// @grant        GM_listValues
// @grant        GM.cookie
// @run-at       document-start
// @license      MIT
// @resource     index-icon.json https://www.bilibili.com/index/index-icon.json
// @resource     protobuf.min.js https://cdn.jsdelivr.net/npm/protobufjs@6.10.1/dist/protobuf.min.js
// @resource     comment.min.js https://cdn.jsdelivr.net/gh/MotooriKashin/Bilibili-Old@c74067196af49a16cb6e520661df7d4d1e7f04e5/src/comment.min.js
// @resource     comment.js https://cdn.jsdelivr.net/gh/MotooriKashin/Bilibili-Old@e8d0df1b4522ec730478d2f84dcbd25cb90d48e8/dist/comment.js
// ==/UserScript==

/**
 * 脚本主体,负责提供脚本与模块间沟通的桥梁
 */
(function () {
    GM.xmlHttpRequest = GM_xmlhttpRequest;
    GM.getValue = GM_getValue;
    GM.setValue = GM_setValue;
    GM.deleteValue = GM_deleteValue;
    GM.listValues = GM_listValues;
    GM.getResourceText = GM_getResourceText;
    GM.getResourceURL = GM_getResourceText;
    // @ts-ignore 忽略unsafeWindow错误
    const root = unsafeWindow;
    const modules = {};
    
    modules["alert.css"] = ".table {\n    line-height: 14px;\n    display: flex;\n    flex-direction: column;\n    box-sizing: border-box;\n    top: 50%;\n    background: #FFFFFF;\n    box-shadow: 0 3px 12px 0 rgb(0 0 0 / 20%);\n    border-radius: 10px;\n    width: 300px;\n    height: auto;\n    padding: 18px;\n    position: fixed;\n    left: 50%;\n    transform: translateX(-50%) translateY(-50%);z-index: 11124;\n}\n.title {\n    line-height: 22px;\n    margin-left: 2px;\n    margin-bottom: 10px;\n    font-size: 14px;\n}\n.text {\n    margin-bottom: 3px;\n    margin-left: 2px;\n}\n.act {\n    line-height: 154%;\n    align-items: center;\n    border-radius: 4px;\n    box-sizing: border-box;\n    cursor: pointer;\n    display: inline-flex;\n    flex-shrink: 0;\n    font-weight: 500;\n    min-width: 5.14em;\n    outline-width: 0;\n    overflow: hidden;\n    padding: 8px 16px;\n    position: relative;\n    user-select: none;\n    border: none;\n    color: #fff;\n    justify-content: space-around;\n}";
    modules["animated-banner.css"] = ".animated-banner {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  right: 0;\n}\n.animated-banner > .layer {\n  position: absolute;\n  left: 0;\n  top: 0;\n  height: 100%;\n  width: 100%;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  overflow: hidden;\n}\n\n@keyframes banner-fade-in {\n  0% {\n    opacity: 0;\n  }\n  100% {\n    opacity: 1;\n  }\n}\n.animated-banner .layer {\n  animation: banner-fade-in 0.7s;\n}\n";
    modules["avatarAnimation.css"] = "/* 鼠标放在顶栏上的动效 */\n.bili-header-m .profile-info .i-face .face{\n    border:0\n}\n.bili-header-m .profile-info .i-face .pendant{\n    transform:scale(0.5);\n    width:112px;\n    height:112px;\n    left:-41px;\n    bottom:-46px;\n    opacity:0;\n    transition:opacity .1s ease-in\n}\n.bili-header-m .profile-info.on .i-face{\n    left:8px;\n    top:0;\n    height:32px;\n    width:32px;\n    transform:translateY(10px) translateX(-16px) scale(2);\n    transform-origin:top left\n}\n.bili-header-m .profile-info.on .i-face .legalize{\n    transform:scale(0.5) translate(10px,15px)\n}\n.bili-header-m .profile-info.on .i-face .pendant{\n    opacity:1\n}\n.bili-header-m .profile-info.on .i-face .face{\n    border:0;\n    box-shadow:0 0 0 2px #fff\n}\n.bili-header-m .profile-info.on .i-face.scale-in{\n    transform:translateY(5px) translateX(-10px) scale(1.75)\n}\n.bili-header-m .profile-info.on .scale-in .face{\n    height:32px;\n    width:32px\n}\n.bili-header-m .profile-info.on .i-face.scale-in .legalize{\n    transform:scale(0.5) translate(38px,48px)\n}";
    modules["bofqi.css"] = "#bofqi .player {\n    width: 980px;\n    height: 620px;\n    display: block;\n}       \n@media screen and (min-width:1400px) {\n    #bofqi .player {\n        width: 1160px;\n        height: 720px\n    }\n}";
    modules["button.css"] = ".button{\n    line-height: 154%;\n    align-items: center;\n    border-radius: 4px;\n    box-sizing: border-box;\n    cursor: pointer;\n    display: inline-flex;\n    flex-shrink: 0;\n    font-weight: 500;\n    height: 32px;\n    justify-content: center;\n    min-width: 5.14em;\n    outline-width: 0;\n    overflow: hidden;\n    padding: 8px 16px;\n    position: relative;\n    user-select: none;\n}\n.button {\n    background-color: #fff;\n    color: rgb(26,115,232);\n    border: 1px solid rgba(0,0,0,6%);\n}\n.button:hover{\n    background-color: rgba(26,115,232,6%);\n}\n.button:active{\n    box-shadow: 0 0 1px 1px rgba(0,0,0,10%);\n}\n.button[disabled]{\n    pointer-events: none;\n    background-color: rgba(239, 239, 239, 0.3);\n    border: 1px solid rgba(118, 118, 118, 0.3);\n    color: rgba(16, 16, 16, 0.3);\n}";
    modules["checkbox.css"] = "/* 复选框 */\n.box {\n  display: inline-flex;\n}\n.checkbox {\n  align-items: center;\n  display: flex;\n  min-height: auto;\n  padding: 0;\n  cursor: pointer;\n}\n.checkbox .checklabel {\n  height: 16px;\n  margin-block-start: 0px;\n  position: relative;\n  width: 16px;\n  border-radius: 50%;\n}\n.checklabel .disc-border {\n  border: 2px solid rgb(95, 99, 104);\n  box-sizing: border-box;\n  height: 16px;\n  width: 16px;\n  border-radius: 50%;\n}\n.checklabel .disc-border[checked] {\n  border-color: rgb(26, 115, 232);\n}\n.checklabel .disc {\n  background-color: transparent;\n  position: absolute;\n  top: 0;\n  transform: scale(0);\n  transition: border-color 200ms, transform 200ms;\n  box-sizing: border-box;\n  height: 16px;\n  width: 16px;\n  border-radius: 50%;\n}\n.checklabel .disc[checked] {\n  background-color: rgb(26, 115, 232);\n  transform: scale(0.5);\n}\n.checkbox .checkvalue {\n  flex: 1;\n  margin-inline-start: 5px;\n  margin-inline-end: 5px;\n}";
    modules["closedCaption.css"] = "/* CC字幕相关样式 */\n/*对齐,悬停按钮显示菜单*/\n#subtitle-setting-panel>div>* {margin-right: 5px;}\n#bilibili-player-subtitle-btn:hover>#subtitle-setting-panel {display: block!important;}\n/*滑动选择样式*/\n#subtitle-setting-panel input[type=\"range\"] {\n    background-color: #ebeff4;\n    -webkit-appearance: none;\n    height:4px;\n    transform: translateY(-4px);\n}\n#subtitle-setting-panel input[type=\"range\"]::-webkit-slider-thumb {\n    -webkit-appearance: none;\n    height: 15px;\n    width: 15px;\n    background: #fff;\n    border-radius: 15px;\n    border: 1px solid;\n}\n/*复选框和其对应标签样式*/\n#subtitle-setting-panel input[type=\"checkbox\"]{display:none;}\n#subtitle-setting-panel input ~ label {cursor:pointer;}\n#subtitle-setting-panel input:checked ~ label:before {content: '\\2714';}\n#subtitle-setting-panel input ~ label:before{\n    width: 12px;\n    height:12px;\n    line-height: 14px;\n    vertical-align: text-bottom;\n    border-radius: 3px;\n    border:1px solid #d3d3d3;\n    display: inline-block;\n    text-align: center;\n    content: ' ';\n}\n/*悬停显示下拉框样式*/\n#subtitle-setting-panel .bpui-selectmenu:hover .bpui-selectmenu-list{display:block;}\n/*滚动条样式*/\n#subtitle-setting-panel ::-webkit-scrollbar{width: 7px;}\n#subtitle-setting-panel ::-webkit-scrollbar-track{border-radius: 4px;background-color: #EEE;}\n#subtitle-setting-panel ::-webkit-scrollbar-thumb{border-radius: 4px;background-color: #999;}";
    modules["commandDm.css"] = ".commandDm-popup {\n  border-radius: 1rem;\n  background-color: #f5f5f5;\n  position: absolute;\n  cursor: default;\n  opacity: 0;\n  transition: opacity 0.2s;\n  padding: 0.8rem 1rem;\n}\n\n.commandDm-popup.on {\n  opacity: 1;\n}\n\n.vote-dialog {\n  overflow: hidden;\n  display: flex;\n  flex-direction: column;\n}\n\n.vote-panel {\n  display: flex;\n  justify-content: space-between;\n  width: 100%;\n}\n\n.vote-title,\n.grade-title {\n  font-weight: bolder;\n  margin-bottom: 0.5rem;\n}\n\n.vote-option {\n  display: flex;\n  flex-direction: column;\n  width: 100%;\n}\n\n.vote-button {\n  text-align: center;\n  min-width: 85px;\n  display: inline-block;\n  padding: 0.3rem 2rem;\n  border: 1px solid #00a1d6;\n  border-radius: 5px;\n  margin: 0.2rem 0;\n  background-color: #fff;\n  cursor: pointer;\n}\n\n.vote-button:hover {\n  background-color: #1baada;\n  color: #f5f5f5;\n  transition: all 0.15s ease-out;\n}\n\n.vote-button::before {\n  position: absolute;\n  padding: 0 1.8rem;\n  left: 0;\n  content: attr(idx);\n}\n\n.vote-progress-bg {\n  border-radius: 5px;\n  min-width: 85px;\n  margin: 0.2rem 0;\n  border: 1px solid #1a1a1a6b;\n  background-color: white;\n  position: relative;\n}\n\n.vote-progress {\n  transition: width 0.3s, background-color 0.2s;\n  animation: opacity-animation 0.5s;\n  overflow: hidden;\n  display: inline-block;\n  border-radius: 4px;\n  background-color: #d3d3d3;\n  text-align: left;\n  overflow: visible;\n  position: relative;\n}\n\n.vote-progress-blue {\n  background-color: #9fdef3;\n}\n\n.vote-progress-desc {\n  display: inline-block;\n  margin: 0.3rem 0.8rem;\n}\n\n@keyframes opacity-animation {\n  from {\n    opacity: 0;\n  }\n  to {\n    opacity: 1;\n  }\n}\n\n.vote-count {\n  display: inline-block;\n  position: absolute;\n  right: 0.8rem;\n  top: 0.3rem;\n}\n\n.vote-count::after {\n  content: \"票\";\n}\n\n.bilibili-player-video-popup {\n  z-index: 100;\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  pointer-events: none;\n}\n\n.bilibili-player-video-popup > * {\n  pointer-events: all;\n}\n\n.link-button {\n  animation: opacity-animation 0.2s;\n  position: absolute;\n  left: 40%;\n  top: 20%;\n  background-color: #f5f5f5;\n  padding: 0.4rem 1rem;\n  border-radius: 0.6rem;\n  font-size: large;\n  box-shadow: #888888c7 0px 0px 6px;\n}\n\n.link-button:hover {\n  color: #00a1d6;\n  cursor: pointer;\n}\n\n.link-button > * {\n  vertical-align: middle;\n}\n\n.link-button > img {\n  transform: scale(0.7) translateY(-1px);\n}\n\n.danmaku-up-icon::before {\n  content: \"UP主\";\n  background-color: #00a1d6;\n  border-radius: 5px;\n  font-size: 0.8em;\n  padding: 0.1em;\n  transform: translateY(-0.1em);\n  display: inline-block;\n  box-shadow: #888888c7 0px 0px 6px;\n}\n\n.grade-score-area > div {\n  display: inline-block;\n  position: relative;\n  width: 41px;\n  transition: width 0.3s;\n}\n\n.grade-score-area.pointer {\n  cursor: pointer;\n}\n\n.grade-score-area > div:last-child {\n  width: 20px;\n}\n\n.grade-score-area .score-button {\n  filter: grayscale(1);\n}\n\n.grade-score-area .highlight .score-button {\n  filter: none;\n}\n\n.grade-score-area .bg {\n  position: absolute;\n  left: 0;\n  filter: blur(9px);\n  visibility: hidden;\n}\n\n.grade-score-area .highlight .bg {\n  visibility: visible;\n}\n\n.grade-score-info {\n  position: absolute;\n  right: 1rem;\n  bottom: 0.6rem;\n  opacity: 0;\n}\n\n@keyframes grade-score-showup {\n  0% {\n    opacity: 0;\n    transform: translateY(5px);\n  }\n  100% {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n\n@keyframes grade-score-hit {\n  0% {\n    filter: brightness(1);\n  }\n  30% {\n    filter: brightness(1.5);\n  }\n  100% {\n    filter: brightness(1);\n  }\n}\n";
    modules["comment.css"] = ".bb-comment .comment-header .header-page, .comment-bilibili-fold .comment-header .header-page {\n    float: right;\n    line-height: 36px;\n}\n.bb-comment .comment-list .list-item .user .text-con, .comment-bilibili-fold .comment-list .list-item .user .text-con {\n    margin-left: initial;\n}\n.bb-comment .comment-list .list-item .reply-box .reply-item .reply-con .user>a, .comment-bilibili-fold .comment-list .list-item .reply-box .reply-item .reply-con .user>a {\n    margin-left: initial;\n}\n.user-card .info .user .vip-icon {\n    max-width: 58px;\n    height: 16px;\n    border-radius: 2px;\n    margin-left: 8px;\n    background-color: #FF6699;\n    font-size: 12px;\n    font-weight: 400;\n    color: #fff;\n    white-space: nowrap;\n    padding: 1px;\n    padding-inline: 4px;\n}\n.user-card .info .verify {\n    color: #9499A0;\n    line-height: 17px;\n    margin-top: 11px;\n}\n.user-card .info .verify .auth {\n    display: inline-block;\n    vertical-align: bottom;\n    position: relative;\n    left: -3px;\n    width: 16px;\n    height: 16px;\n}\n.reply-item .reply-con .user .stick {\n    zoom: 0.9;\n}";
    modules["danmakuHashId.css"] = "/* 反查弹幕发送者相关样式 */\n.bb-comment, .comment-bilibili-fold {\n    font-family: Microsoft YaHei,Arial,Helvetica,sans-serif;\n    font-size: 0;\n    zoom: 1;\n    min-height: 100px;\n    background: #fff;\n}.bb-comment .comment-list, .comment-bilibili-fold .comment-list {\n    padding-top: 20px;\n}.bb-comment *, .comment-bilibili-fold * {\n    box-sizing: content-box;\n}.bb-comment .comment-list .list-item .reply-box .reply-item .reply-face, .comment-bilibili-fold .comment-list .list-item .reply-box .reply-item .reply-face {\n    display: inline-block;\n    position: relative;\n    margin-right: 10px;\n    vertical-align: top;\n}.bb-comment .comment-list .list-item .reply-box .reply-item .reply-face img, .comment-bilibili-fold .comment-list .list-item .reply-box .reply-item .reply-face img {\n    width: 24px;\n    height: 24px;\n    border-radius: 50%;\n}.bb-comment .comment-list .list-item .reply-box .reply-item .reply-con, .comment-bilibili-fold .comment-list .list-item .reply-box .reply-item .reply-con {\n    display: inline-block;\n    width: calc(100% - 34px);\n}.bb-comment .comment-list .list-item .user, .comment-bilibili-fold .comment-list .list-item .user {\n    font-size: 12px;\n    font-weight: 700;\n    line-height: 18px;\n    padding-bottom: 4px;\n    display: block;\n    word-wrap: break-word;\n    position: relative;\n}.bb-comment .comment-list .list-item .reply-box .reply-item .reply-con .user .name, .comment-bilibili-fold .comment-list .list-item .reply-box .reply-item .reply-con .user .name {\n    position: relative;\n    top: -1px;\n}.bb-comment .comment-list .list-item .reply-box .reply-item .level, .comment-bilibili-fold .comment-list .list-item .reply-box .reply-item .level {\n    margin: 0 15px 0 8px;\n}.bb-comment .comment-list .list-item .user .level.l0,.comment-bilibili-fold .comment-list .list-item .user .level.l0 {\n    background-position: -23px -28px\n}.bb-comment .comment-list .list-item .user .level.l1,.comment-bilibili-fold .comment-list .list-item .user .level.l1 {\n    background-position: -23px -92px\n}.bb-comment .comment-list .list-item .user .level.l2,.comment-bilibili-fold .comment-list .list-item .user .level.l2 {\n    background-position: -23px -156px\n}.bb-comment .comment-list .list-item .user .level.l3,.comment-bilibili-fold .comment-list .list-item .user .level.l3 {\n    background-position: -23px -220px\n}.bb-comment .comment-list .list-item .user .level.l4,.comment-bilibili-fold .comment-list .list-item .user .level.l4 {\n    background-position: -23px -284px\n}.bb-comment .comment-list .list-item .user .level.l5,.comment-bilibili-fold .comment-list .list-item .user .level.l5 {\n    background-position: -23px -348px\n}.bb-comment .comment-list .list-item .user .level.l6,.comment-bilibili-fold .comment-list .list-item .user .level.l6 {\n    background-position: -23px -412px\n}.bb-comment .comment-list .list-item .user .level.l7,.comment-bilibili-fold .comment-list .list-item .user .level.l7 {\n    background-position: -23px -476px\n}.bb-comment .comment-list .list-item .user .level.l8,.comment-bilibili-fold .comment-list .list-item .user .level.l8 {\n    background-position: -23px -540px\n}.bb-comment .comment-list .list-item .user .level.l9,.comment-bilibili-fold .comment-list .list-item .user .level.l9 {\n    background-position: -23px -604px\n}.bb-comment .comment-list .list-item .user .level, .comment-bilibili-fold .comment-list .list-item .user .level {\n    display: inline-block;\n    width: 19px;\n    height: 9px;\n    vertical-align: middle;\n    margin: 0 8px;\n    background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA+gAAAPoCAMAAAB6fSTWAAAA51BMVEUAAACYoKhwd3yboqni5emDjJL7+/yZoqoAodbnix8AodYAodaZoqoAodYAodaln5jnix8Aodbnix8AodaZoqoAodbnix8Aodbnix/yXY6ZoqoAodYAodYAodaZoqoAodaZoqryXY7yXY4AodbyXY6ZoqryXY6ZoqoAodaZoqoAodaZoqryXY7nix8AodYAodbnix+ZoqqZoqrnix8AodYAodbnix+Zoqr////19vfM0NcAoda/v7/l6e9MyP//u1PlL+z/s3yS0eWV3bL/bAAVFRX/AACEHPnnix+M2fn/1pbyXY4iIiIkv4BgAAAAOHRSTlMA9fUreZKu4eI+EfDtgtwP7AkexYcv2WfIsP3refnX0mcmGUPyxsScjXkXF++zoZpMMyn+Ppl8Q6/LsKoAAA3QSURBVHja7NvdbtowGIfxP7UsaEqbfkGj0bWVpqofiK0f2nZALyD3f0V7E4KsbULCjpRA9fykQDjw4SOb2BEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG2cF4X64vzAeJc+/sDYeGDH3Q0e1MrV1x9q4eW0LNUTP2j4xPEHDS9gp70O50O1MRk9j5Tu13tZhX4+LdS5ejJvpnUlqCfzZloXsMPym99qFfrZ7Telh54vyop1Xk7VNevbqeas+KT5fD2eOR3b+FhR1/L84dJaz42SZNnPR2UnWZadKV7+Mi1rss7P1THXdB7u47iq83DP/3RsijtQpevQ78bjL/fS29CMHxTvana0vDjT5MTMviuSVb6movvO5Qe+Wr2vLvsRP6H7avW+ujxTOjaErrrw+mq+1K1hrqHWxoo3yjTS2kyRTssQeh9sEg+hO/uIZJN4CN3xLx07G7pC6G/3KaErhD65UKQyUGEfhbplaYfQlRK6Quja29CPj4W/febQn55ahn59vY+hO9VcWuhh/P6GfrxcUvq/PnHo965l6BcTRZruwNLdexnv05buYfzeLt2tc0qPkBi6qb77D31+o3ahP58o1mERQl8U/TyMc3bZjUt9GOfsshvHwzhsDt00jdf3fYZ+d9ky9KtHxcsPe99ec746NJO+veZ8dWiG7TVs9PGfzkOfr0PPb16TQn9eh57dTtoemCm0NQ7MAHH76OOVJylxH/2oNrtufQR2oa1xBBbYN/ZSy7ui8VILsF94TRUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAH3buoMVNIAzA8BxESA5ldyHkUui1p/Y6YrJ71v//g/rFmFoKaaMBdZPngTWzh+/4MqKTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwIMqyirnqizungfWqihzryzum5c6rFVkWrUfoa0i1Unzx+Y9NMfTPKzZvv6ZnlJ02n702ih1wnzz3muUzrrt6rpOS3kbFrMrzp0PpRdj57vOh9LdvbNer/WCob+9bFJn8zJ/6eWl87Y9l16OnW/6xpvuakvnvw5naW7bbX2y3W5f0xI2UXr/MbciV33nffBVLsbNH/vO++CPtnSuxT3o/k/z2td/+JGWEIkv0vmwobf596KcsqE3ORa2dK46nNLuLsNiXpF3/F2kRUTkC3QeqnzpPBadXI2bv3Qei07Mg9CvlR6dLyDnc+ehqqou9Dxu/tJ5zB+70HOCtYf+Nd3sgUKvcqedGno/3widTxL6Lt3skW7do+/ofPKtezh17tadf4YeTp8rCP1Lup2HcR7GMSL00BfeNb5o6N/TzR7r9Vobnd/zeq2Jzr1e47rD35YM/dsujfMwB2bauE4/MNMdl7Ghs2r7+o5HcY7AOgILn4AvtcAz8DVVeAZ+eAKegp+SAgAAAAAAAAAAAAAAAAAAAH6xczctbQRxAIf/RmHDGgyiQWisCkV8gxaF0nZDTjkF+v0/T4dNrIFe6g5JnOR5srksDHP6wTCzDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlKhZdXRY3HjgPzS/Vkybd5fW/FyRxmfOr3RorS/0ZHqUEXqSxufODyRrDD1pckJPmuz5gQihQxc3g8GnwcJDdHAxPp4ct8aXUR6hsx+qp6iiNbx6jvfrP0Y/WvX1KIojdDZtthCbVbVP6+a8S+jt07q4j+IsQjvIDH2eGfpU6Dtutioi2WLoT1d5oT+eRHEWof0+yAt9Ms8LvZkKfbfNoi28/be2GXrcHmaFHmflrd2XoafSs0KfzPNCb6ZC32kfK/SHh7zQL8vbjluGnkrPC30yzwu9mQp9l62Evv2le7zc5oU+OovS/A29J3Q66BT6Vjbjhm+hx6BD6PVb6DGO0ryG3rN0Z41e406/jNBzz9FvI16qZHDX7Rz97DRGJ8n4a5RmGXrPZhzr1Gb92vjyzaYNh3fnMbwaJtFFXX+/j/qkruvTKM4itJ7jNdZq9q/YuFT5j6iiu9PrL9GPIvlghj3yXD1VkWHUfxS60Pnwbg7uIsfF529RJKHDHhA67AEXT8AecJUU7IHG5ZAAAAAAAAAAAAAAAMAfdu6etUEgDuDwNcnkUMgQshS6dmrXeOKSLdDv/3kqlxeELCVXk9T/84Aogtz0w+OUAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAmVqu8ti/ex74RWe5b8dueH43Vj0+8PdWfVsV2mrofOyG8YUOU8ttXWh5Vxd6boUOV4QOt9h2F28pHqETwxD4cBTvmxSO0Lm3/VGqUBd695HCuYT2Uhn6oTL0Xuhzth8rdx4Z+msKJ587/64L/dDVhd5noc/ZPpXCy1E8LPQi3tw9nzuvC/3Q1YXeZ6HP2pOFHm85Lp86rwv90NWF3mehz9so9CeYug+X0Rz7WgidKzN+o0cN3dSdaZ36LufHhL7tRj5TNLk9WliMY0Il69J3xap7paYpkTdNs07h5PZk4fMa09lfS/e3Djlr98MM0WyELnQC2HZfKSShQwBChwBsPAEB2EoKIljaHBIAAAAAAAAAAPhhzw5WGwSiMIzekCGbkF1Wgb5HhzIL3/+lClaCEixCCMl4zwER3H/8OgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADtX2gYlgJ617w1aAD0TOiQgdEhA6JCA0CEBoUMCQocEhA4JCB0SEDokIHRIQOiQgNBJ6nq4xlMu50t0Q+gkdbsd4ilfP+fohtB5o+FPbGTRhU4vhrkYr+CB0OnbEPfChb5O6PTtU0L36i505l4Z+vRkI4dxQqcXi9AHi75C6PRt6nu6+0ZfIXT6NmY99i30/widrg0z/qOvEjo4jBM6WHShQ0ZChwSEDgkIHRIQOiQgdEhA6JDAQ+i1tSp02Je2rLy2cjyWVqvQYUfaYsxPJUbl1KrQYTfaYszjbpx1of+yZ8c4DINAFAW3QJwpFO64/5kiMAUU6eP1jGS5oH76loEcajvGfDlnvdUAnqxc7dOuY8yPWZ/HJYBHK3WN+e9jnQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPyNfgsgmb6LQeiQTo9Z+P2ERYeUhA4vsIXu0x2y2kOfhA75rL7HW+iQ1cx69O2vO+TVN+7RAQAAAAAAAAAAvuzZwQnAIBBE0a1u+i8pqBch15wm74FawWdFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvpFjgDK5zSJ0qJPZhZ81JjpUEjr8wBW6qzu0ek10oUOfTJZ1Ch1aZW/JeHWHXrn4RwcAAAAAAHjYs2MbgIEQCIKURv9VWY8dfAGOjhkJUcFGBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8I9+FRCmb3UIHeJ0TeFzQ+iQR+iwgNBhAaHDAl/f5wsdUk3W07fQIVZf7OgAAAAPe3ZQA0AIQ1Gw7r5/Rxu6lwrgVGYSqIIXCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANyRXwHLZKpD6LBOqgvv1UPosI/Q4QEjdFd32MqJDg9I5ThT6LBVekvKqzvslcE/+sduHZ0AAIIAFHQ5918pMggH6MvuQJzgoQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG/kEcAw2cUmdBgnowqvqSV0mEfo8IEWutcdprqh17joiz07tgEQhgEgmBoEUuQaZZDU3n8lCBUbIFl3hT3BNzaUlC2XtYUOVeU7MpurO9SVH/7oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL+L+YgGVBZzaUBp2xA6FNaP8zqPmEPoUFaPueyxCf1mz45NIIaBIAAqdCKBcOTAgZBDh86uhO+/n9fzTZhjJtgOloNbSKtGm322qGX3jIOsWjwrn2gFSOuMvrLHWYC0WkwXHbKrsc0+t6gFSKvv8bP3AuT139H1HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4OXGcV3HKEBi4/4st6Z/2bODG4BhEAaArJFnoyjLeP99WnUMuHuwgQXC0NnK2vsbBfR1sqt2TgF9CToM4HSHATzjYIJnJeo16O3mdwvoS9BhhqSA7q51DgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAve3AgAAAAAADk/9oIqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqrCHhwIAAAAAAD5vzaCqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqwBwcCAAAAAED+r42gqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqirtwQEJAAAAgKD/r9sRqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8BfEgGFMI1IvvAAAAABJRU5ErkJggg==) no-repeat;\n}";
    modules["download.css"] = ".table {\n    position: fixed;\n    z-index: 11113;\n    bottom: 0;\n    width: 100%;\n    min-height: 50px;\n    display: flex;\n    box-sizing: border-box;\n    background: #fff;\n    border-radius: 8px;\n    box-shadow: 0 6px 12px 0 rgba(106, 115, 133, 22%);\n    transition: transform 0.3s ease-in;\n    flex-wrap: wrap;\n    align-content: center;\n    justify-content: center;\n    align-items: center;\n}\n.cell {\n    background-color: #fff;\n    color: #000 !important;\n    border: #ccc 1px solid;\n    border-radius: 3px;\n    display: flex;\n    margin: 3px;\n    flex-wrap: wrap;\n    align-content: center;\n    justify-content: center;\n    align-items: center;\n    flex-direction: row;\n}\n.type {\n    color: #000 !important;\n    display: table-cell;\n    min-width: 1.5em;\n    text-align: center;\n    vertical-align: middle;\n    padding: 10px 3px;\n}\n.item {\n    display: table-cell;\n    text-decoration: none;\n    padding: 3px;\n    cursor: pointer;\n    color: #1184B4;\n}\n.item:hover {\n    color:#FE3676;\n}\n.up {\n    color: #fff !important;\n    text-align: center;\n    padding: 1px 3px;\n    background-color: #777;\n}\n.down {\n    font-size: 90%;\n    margin-top: 2px;\n    text-align: center;\n    padding: 1px 3px;\n}";
    modules["hr.css"] = ".hr {\n    display: flex;\n    align-items: center;\n    grid-gap: 0;\n    gap: 0;\n    justify-content: space-between;\n    flex-shrink: 0;\n    height: 1px;\n    background-color: rgba(136,136,136,0.1);\n    width: 100%;\n    margin-bottom: 12px;\n}";
    modules["icon.css"] = ".icon {\n  align-items: center;\n  border-radius: 50%;\n  display: flex;\n  height: 20px;\n  justify-content: center;\n  position: relative;\n  width: 20px;\n  box-sizing: content-box;\n  background: none;\n  cursor: pointer;\n}\n";
    modules["imroot.css"] = "/* 修复顶栏样式 */\n.im-root,.im-root .im-list-box * {\n    font-size:12px;\n    line-height:42px;\n}\n.im-root .im-list-box {\n    width:100%;\n    overflow:visible;\n}\n.im-root .im-list-box .im-list {\n    line-height:42px;\n    height:42px;\n}\n.im-root .im-list-box .im-notify.im-number {\n    height: 14px;\n    line-height: 13px;\n    border-radius: 10px;\n    padding: 1px 3px;\n    font-size: 12px;\n    min-width: 20px;\n    text-align: center;\n    color: #fff;\n}\n.im-root .im-list-box .im-notify.im-number.im-center {\n    top: 14px;\n    left: 80px;\n}\n.im-root .im-list-box .im-notify.im-dot {\n    top: 11px;\n    right: -10px;\n    width: 8px;\n    height: 8px;\n    border-radius: 100%;\n}\n.im-root .im-list-box .im-notify.im-dot.im-center {\n    top: 16px;\n    right: 20px;\n}";
    modules["input.css"] = "/* 输入框 */\n.input {\n  align-items: center;\n  display: flex;\n  justify-content: space-between;\n  position: relative;\n  background-color: transparent;\n  box-sizing: border-box;\n  padding: 0;\n  flex: 1;\n  flex-basis: 0.000000001px;\n  padding-block-end: 12px;\n  padding-block-start: 12px;\n}\n.input input {\n  background-color: transparent;\n  box-sizing: border-box;\n  font-family: inherit;\n  font-size: inherit;\n  font-weight: inherit;\n  line-height: inherit;\n  min-height: auto;\n  outline: none;\n  padding-bottom: 6px;\n  padding-inline-end: 8px;\n  padding-inline-start: 8px;\n  padding-top: 6px;\n  text-align: inherit;\n  text-overflow: ellipsis;\n  width: 100%;\n  border-radius: 4px;\n  border: 1px solid rgba(136, 136, 136, 0.13333);\n  box-shadow: 0 4px 12px 0 rgb(0, 0, 0, 5%);\n  transition: box-shadow 120ms ease 180ms;\n}\n.input input:focus {\n  box-shadow: inset 0 0 1px 1px rgba(26, 115, 232, 80%);\n}\n.input .icon {\n  cursor: pointer;\n  outline: none;\n  padding: 0;\n  pointer-events: auto;\n  position: absolute;\n  right: 12px;\n  background-color: white;\n}\n.input .icon:hover {\n  background-color: rgba(0, 0, 0, 10%);\n  box-shadow: 0 1 12px 12px rgb(0, 0, 0, 10%);\n}";
    modules["message.css"] = "/* 修复消息页样式 */\n.container[data-v-6969394c] { \n    height: calc(100vh - 42px) !important;\n} \n.container[data-v-1c9150a9] { \n    height: calc(100vh - 42px) !important;\n}";
    modules["mini-bofqi.css"] = "/* 修正稍后再看迷你播放器样式 */\n.bilibili-player .bilibili-player-area .bilibili-player-video-wrap.mini-player .bilibili-player-video-danmaku {\n    top: 30px;\n    height: 240px;\n}";
    modules["oldReplySort.css"] = ".bb-comment .comment-list .list-item .user-face img, .comment-bilibili-fold .comment-list .list-item .user-face img {\n    width: 48px;\n    height: 48px;\n    border-radius: 50%;\n}\n.bb-comment .comment-list .list-item .user-face .pendant, .comment-bilibili-fold .comment-list .list-item .user-face .pendant {\n    width: 86px;\n    height: 86px;\n    position: absolute;\n    top: -19px;\n    left: -19px;\n    display: block;\n}\n.bb-comment .comment-list .list-item .user-face .pendant img, .comment-bilibili-fold .comment-list .list-item .user-face .pendant img {\n    border: 0;\n    border-radius: 0;\n    width: 86px;\n    height: 86px;\n}";
    modules["progress.css"] = ".progress{\n    --paper-progress-active-color: rgb(26,115,232);\n    --paper-progress-container-color: rgb(223, 222, 223);\n    width: auto;\n}\n.progressContainer{\n    background: rgb(223, 222, 223);\n    height: 4px;\n    position: relative;\n}\n.secondaryProgress,.primaryProgress{\n    \n    position: absolute;\n    top: 0;\n    right: 0;\n    bottom: 0;\n    left: 0;\n    transform-origin: left center;\n    transform: scaleX(0);\n    will-change: transform;\n}\n.secondaryProgress{\n    background: rgb(183, 225, 205);\n}\n.primaryProgress{\n    background: rgb(26,115,232);\n}\n.progressTag{\n    width: 100%;\n    padding-top: 6px;\n    display: inline-flex;\n    justify-content: space-between;\n}";
    modules["select.css"] = "/* 下拉列表 */\n.select {\n  align-items: center;\n  display: inline-flex;\n}\nselect {\n  background-color: rgb(241, 243, 244);\n  background-size: 10px;\n  border: none;\n  border-radius: 4px;\n  color: rgb(32, 33, 36);\n  cursor: pointer;\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n  max-width: 100%;\n  outline: none;\n  padding-bottom: 6px;\n  padding-inline-end: 21px;\n  padding-inline-start: 8px;\n  padding-top: 6px;\n  width: 200px;\n}\noption {\n  background-color: #fff;\n}";
    modules["switch.css"] = "/* 滑块开关 */\n.switch {\n  cursor: pointer;\n  display: block;\n  min-width: 34px;\n  outline: none;\n  position: relative;\n  width: 34px;\n}\n.bar {\n  background-color: rgb(189, 193, 198);\n  border-radius: 8px;\n  height: 12px;\n  left: 3px;\n  position: absolute;\n  top: 2px;\n  transition: background-color linear 80ms;\n  width: 28px;\n  z-index: 0;\n}\n.bar[checked] {\n  background-color: rgb(26, 115, 232);\n  opacity: 0.5;\n}\n.bar:active {\n  box-shadow: 0 0 1px 1px rgba(26, 115, 232, 80%);\n}\n.knob {\n  background-color: #fff;\n  border-radius: 50%;\n  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 40%);\n  display: block;\n  height: 16px;\n  position: relative;\n  transition: transform linear 80ms, background-color linear 80ms;\n  width: 16px;\n  z-index: 1;\n}\n.knob[checked] {\n  background-color: rgb(26, 115, 232);\n  transform: translate3d(18px, 0, 0);\n}\n.knob:active {\n  box-shadow: 0 0 1px 1px rgba(26, 115, 232, 80%);\n}\n.knob i {\n  color: rgba(128, 134, 139, 15%);\n  height: 40px;\n  left: -12px;\n  pointer-events: none;\n  top: -12px;\n  transition: color linear 80ms;\n  width: 40px;\n  border-radius: 50%;\n  bottom: 0;\n  display: block;\n  overflow: hidden;\n  position: absolute;\n  right: 0;\n  transform: translate3d(0, 0, 0);\n}\n.knob i[checked] {\n  color: rgb(26, 115, 232);\n}\n.knob i:active {\n  box-shadow: 0 0 1px 1px rgba(26, 115, 232, 80%);\n}";
    modules["ui-action.css"] = ".contain {\n  align-items: center;\n  border-top: 1px solid rgba(0, 0, 0, 6%);\n  display: flex;\n  min-height: 24px;\n  padding: 0 20px;\n  flex-wrap: wrap;\n  justify-content: flex-end;\n  background-color: transparent !important;\n}\n.label {\n  flex: 1;\n  flex-basis: 0.000000001px;\n  padding-block-end: 12px;\n  padding-block-start: 12px;\n  padding-inline-start: 12px;\n}\n.sub {\n  color: rgb(95, 99, 104);\n  font-weight: 400;\n}\n.button,\n.action {\n  line-height: 154%;\n  align-items: center;\n  border-radius: 4px;\n  box-sizing: border-box;\n  cursor: pointer;\n  display: inline-flex;\n  flex-shrink: 0;\n  font-weight: 500;\n  height: 32px;\n  justify-content: center;\n  min-width: 5.14em;\n  outline-width: 0;\n  overflow: hidden;\n  padding: 8px 16px;\n  position: relative;\n  user-select: none;\n}\n.action {\n  border: none;\n  background-color: rgb(26, 115, 232);\n  color: #fff;\n}\n.button {\n  background-color: #fff;\n  color: rgb(26, 115, 232);\n  border: 1px solid rgba(0, 0, 0, 6%);\n}\n.action:hover {\n  background-color: rgb(72, 115, 232);\n}\n.button:hover {\n  background-color: rgba(26, 115, 232, 6%);\n}\n.action:active {\n  box-shadow: 0 0 1px 1px rgba(72, 115, 232, 80%);\n}\n.button:active {\n  box-shadow: 0 0 1px 1px rgba(0, 0, 0, 10%);\n}\n.button[disabled],\n.action[disabled] {\n  pointer-events: none;\n  background-color: rgba(19, 1, 1, 0.1);\n  border: 1px solid rgba(0, 0, 0, 0.1);\n  color: white;\n}\n";
    modules["ui-contain.css"] = ".contain {\n  margin-bottom: 3px;\n  padding-inline-start: 20px;\n  padding-inline-end: 20px;\n  display: flex;\n  flex-direction: column;\n  outline: none;\n  position: relative;\n}\n.header .title {\n  color: #000;\n  font-size: 108%;\n  font-weight: 400;\n  letter-spacing: 0.25px;\n  margin-bottom: 12px;\n  margin-top: 21px;\n  outline: none;\n  padding-bottom: 4px;\n  padding-top: 8px;\n}\n.card {\n  border-radius: 4px;\n  box-shadow: 0px 0px 1px 1px rgba(60, 64, 67, 30%);\n  flex: 1;\n  color: #000;\n  line-height: 154%;\n  user-select: text;\n}\n";
    modules["ui-file.css"] = ".contain {\n  align-items: center;\n  border-top: 1px solid rgba(0, 0, 0, 6%);\n  display: flex;\n  min-height: 24px;\n  padding: 0 20px;\n  flex-wrap: wrap;\n  justify-content: flex-end;\n  background-color: transparent !important;\n}\n.label {\n  flex: 1;\n  flex-basis: 0.000000001px;\n  padding-block-end: 12px;\n  padding-block-start: 12px;\n  padding-inline-start: 12px;\n}\n.sub {\n  color: rgb(95, 99, 104);\n  font-weight: 400;\n}\n.button,\n.action {\n  line-height: 154%;\n  align-items: center;\n  border-radius: 4px;\n  box-sizing: border-box;\n  cursor: pointer;\n  display: inline-flex;\n  flex-shrink: 0;\n  font-weight: 500;\n  height: 32px;\n  justify-content: center;\n  min-width: 5.14em;\n  outline-width: 0;\n  overflow: hidden;\n  padding: 8px 16px;\n  position: relative;\n  user-select: none;\n}\n.action {\n  border: none;\n  background-color: rgb(26, 115, 232);\n  color: #fff;\n}\n.button {\n  background-color: #fff;\n  color: rgb(26, 115, 232);\n  border: 1px solid rgba(0, 0, 0, 6%);\n}\n.action:hover {\n  background-color: rgb(72, 115, 232);\n}\n.button:hover {\n  background-color: rgba(26, 115, 232, 6%);\n}\n.action:active {\n  box-shadow: 0 0 1px 1px rgba(72, 115, 232, 80%);\n}\n.button:active {\n  box-shadow: 0 0 1px 1px rgba(0, 0, 0, 10%);\n}\n.button[disabled],\n.action[disabled] {\n  pointer-events: none;\n  background-color: rgba(19, 1, 1, 0.1);\n  border: 1px solid rgba(0, 0, 0, 0.1);\n  color: white;\n}\n";
    modules["ui-float.css"] = ".float {\n  top: 0;\n  right: 0;\n  position: fixed;\n  z-index: 11111;\n  min-width: 40px;\n  min-height: 30px;\n  display: block;\n  padding: 8px;\n  box-sizing: border-box;\n  background: #fff;\n  border: 1px solid #e9eaec;\n  border-radius: 8px;\n  box-shadow: 0 6px 12px 0 rgb(106, 115, 133, 22%);\n  user-select: text;\n  pointer-events: none;\n}\n.arrow {\n  left: 16%;\n  top: 100%;\n  width: 0;\n  height: 0;\n  border-left: 4px solid transparent;\n  border-right: 4px solid transparent;\n  border-top: 8px solid #fff;\n  position: absolute;\n  user-select: text;\n}\n.message {\n  margin-top: -4px;\n  box-sizing: border-box;\n  height: 100%;\n  position: relative;\n  user-select: text;\n  word-wrap: break-word;\n  word-break: break-all;\n  font-size: 12px;\n  line-height: 1.15;\n}\n";
    modules["ui-input.css"] = ".contain {\n  align-items: center;\n  border-top: 1px solid rgba(0, 0, 0, 6%);\n  display: flex;\n  min-height: 24px;\n  padding: 0 20px;\n  flex-wrap: wrap;\n  justify-content: flex-end;\n  background-color: transparent !important;\n}\n.label {\n  flex: 1;\n  flex-basis: 0.000000001px;\n  padding-block-end: 12px;\n  padding-block-start: 12px;\n  padding-inline-start: 12px;\n}\n.sub {\n  color: rgb(95, 99, 104);\n  font-weight: 400;\n}\n.textbox {\n  align-items: center;\n  display: flex;\n  justify-content: space-between;\n  position: relative;\n  background-color: transparent;\n  box-sizing: border-box;\n  padding: 0;\n  flex: 1;\n  flex-basis: 0.000000001px;\n  padding-block-end: 12px;\n  padding-block-start: 12px;\n}\n.textbox input {\n  background-color: transparent;\n  box-sizing: border-box;\n  font-family: inherit;\n  font-size: inherit;\n  font-weight: inherit;\n  line-height: inherit;\n  min-height: auto;\n  outline: none;\n  padding-bottom: 6px;\n  padding-inline-end: 8px;\n  padding-inline-start: 8px;\n  padding-top: 6px;\n  text-align: inherit;\n  text-overflow: ellipsis;\n  width: 100%;\n  border-radius: 4px;\n  border: 1px solid rgba(136, 136, 136, 0.13333);\n  box-shadow: 0 4px 12px 0 rgb(0, 0, 0, 5%);\n  transition: box-shadow 120ms ease 180ms;\n}\n.textbox input:focus {\n  box-shadow: inset 0 0 1px 1px rgba(26, 115, 232, 80%);\n}\n.textbox .icon {\n  cursor: pointer;\n  outline: none;\n  padding: 0;\n  pointer-events: auto;\n  position: absolute;\n  right: 12px;\n  background-color: white;\n}\n.textbox .icon:hover {\n  background-color: rgba(0, 0, 0, 10%);\n  box-shadow: 0 1 12px 12px rgb(0, 0, 0, 10%);\n}\n.button,\n.action {\n  line-height: 154%;\n  align-items: center;\n  border-radius: 4px;\n  box-sizing: border-box;\n  cursor: pointer;\n  display: inline-flex;\n  flex-shrink: 0;\n  font-weight: 500;\n  height: 32px;\n  justify-content: center;\n  min-width: 5.14em;\n  outline-width: 0;\n  overflow: hidden;\n  padding: 8px 16px;\n  position: relative;\n  user-select: none;\n}\n.action {\n  border: none;\n  background-color: rgb(26, 115, 232);\n  color: #fff;\n}\n.button {\n  background-color: #fff;\n  color: rgb(26, 115, 232);\n  border: 1px solid rgba(0, 0, 0, 6%);\n}\n.action:hover {\n  background-color: rgb(72, 115, 232);\n}\n.button:hover {\n  background-color: rgba(26, 115, 232, 6%);\n}\n.action:active {\n  box-shadow: 0 0 1px 1px rgba(72, 115, 232, 80%);\n}\n.button:active {\n  box-shadow: 0 0 1px 1px rgba(0, 0, 0, 10%);\n}\n.button[disabled],\n.action[disabled] {\n  pointer-events: none;\n  background-color: rgba(19, 1, 1, 0.1);\n  border: 1px solid rgba(0, 0, 0, 0.1);\n  color: white;\n}\n";
    modules["ui-item.css"] = "/* 菜单项容器 */\n.contain {\n  align-items: center;\n  border-top: 1px solid rgba(0, 0, 0, 6%);\n  display: flex;\n  min-height: 24px;\n  padding: 0 20px;\n  flex-wrap: wrap;\n  justify-content: flex-end;\n  background-color: transparent !important;\n}\n.label {\n  flex: 1;\n  flex-basis: 0.000000001px;\n  padding-block-end: 12px;\n  padding-block-start: 12px;\n  padding-inline-start: 12px;\n}\n.sub {\n  color: rgb(95, 99, 104);\n  font-weight: 400;\n}\n";
    modules["ui-menu.css"] = ".menuitem {\n  align-items: center;\n  display: flex;\n  font-weight: 500;\n  margin-inline-end: 2px;\n  margin-inline-start: 1px;\n  min-height: 20px;\n  padding-bottom: 10px;\n  padding-inline-start: 23px;\n  padding-top: 10px;\n  cursor: pointer;\n}\n.menuitem:hover {\n  background-color: rgb(0, 0, 0, 6%);\n}\n.menuitem > div {\n  padding-inline-end: 12px;\n}\n";
    modules["ui-picture.css"] = ".contain {\n  align-items: center;\n  border-top: 1px solid rgba(0, 0, 0, 6%);\n  display: flex;\n  min-height: 24px;\n  padding: 0 20px;\n  flex-wrap: wrap;\n  justify-content: center;\n  background-color: transparent !important;\n  line-height: 0;\n  max-height: 62px;\n}\n.contain img {\n  border-radius: 4px;\n  width: 100%;\n  max-height: 62px;\n}\n";
    modules["ui-popup-box.css"] = ".box{\n    top: 50%;\n    left: 50%;\n    transform: translateX(-50%) translateY(-50%);\n    transition: 0.3s cubic-bezier(0.22, 0.61, 0.36, 1);\n    padding: 12px;\n    background-color: #fff;\n    color: black;\n    border-radius: 8px;\n    box-shadow: 0 4px 12px 0 rgb(0 0 0 / 5%);\n    border: 1px solid rgba(136,136,136,0.13333);\n    box-sizing: border-box;\n    position: fixed;\n    font-size: 13px;\n    z-index: 11115;\n    line-height: 14px;\n}\n.contain{\n    display: flex;\n    flex-direction: column;\n    height: 100%;\n}\n*::-webkit-scrollbar {\n  width: 0 !important;\n  height: 0 !important;\n}";
    modules["ui-sort-body.css"] = "contain {\n  display: block;\n  padding-block-end: 0;\n  padding-block-start: 0;\n  padding-inline-end: 20px;\n  padding-inline-start: 20px;\n  border-top: 1px solid rgba(0, 0, 0, 6%);\n}\n";
    modules["ui-sort-head.css"] = ".contain {\n  align-items: center;\n  border-top: 1px solid rgba(0, 0, 0, 6%);\n  display: flex;\n  min-height: 24px;\n  padding: 0 20px;\n  flex-wrap: wrap;\n  justify-content: flex-end;\n  background-color: transparent !important;\n}\n.label {\n  flex: 1;\n  flex-basis: 0.000000001px;\n  padding-block-end: 12px;\n  padding-block-start: 12px;\n  padding-inline-start: 12px;\n}\n.sub {\n  color: rgb(95, 99, 104);\n  font-weight: 400;\n}\n.anchor {\n  cursor: pointer;\n  transition: transform 120ms ease 180ms, box-shadow 120ms ease 180ms;\n}\n.anchor[checked] {\n  transform: rotateX(180deg);\n}\n.anchor:hover {\n  box-shadow: 0 0 4px 4px rgba(241, 243, 244, 80%);\n}\n";
    modules["ui-stage.css"] = ".stage {\n  position: fixed;\n  right: 40px;\n  bottom: 60px;\n  height: 20px;\n  width: 20px;\n  border: 1px solid #e9eaec;\n  border-radius: 50%;\n  box-shadow: 0 0 12px 4px rgb(106, 115, 133, 22%);\n  padding: 10px;\n  cursor: pointer;\n  animation: roll 1s ease-out;\n  transition: opacity 0.3s ease-out;\n  background: none;\n  z-index: 11110;\n}\n.classical{\n  box-sizing: content-box;\n  color: #fff;\n  background-color: #fff;\n  border-radius: 5px;\n  position: fixed;\n  bottom: 65px;\n  width: 56px;\n  height: 40px;\n  transition: right 0.7s;\n  -moz-transition: right 0.7s;\n  -webkit-transition: right 0.7s;\n  -o-transition: right 0.7s;\n  z-index: 11110;\n  padding: 4px;\n  right : -54px;\n}\n.classical:hover{\n  right : 0px;\n  box-shadow : rgba(0, 85, 255, 0.098) 0px 0px 20px 0px;\n  border : 1px solid rgb(233, 234, 236);\n}\n.classical i{\n  background-position: -471px -982px;\n  display: block;\n  width: 20px;\n  height: 20px;\n  transition: 0.2s;\n  background-image: url(//static.hdslb.com/images/base/icons.png);\n  margin: auto;\n}\n.classical span{\n  font-size: 14px;\n  display: block;\n  width: 50%;\n  transition: 0.2s;\n  color: #000;\n  margin: auto;\n}\n@keyframes roll {\n  30%,\n  60%,\n  90% {\n    transform: scale(1) rotate(0deg);\n  }\n  10%,\n  40%,\n  70% {\n    transform: scale(1.11) rotate(-180deg);\n  }\n  20%,\n  50%,\n  80% {\n    transform: scale(0.9) rotate(-360deg);\n  }\n}\n";
    modules["ui.css"] = ".box {\n  left: 50%;\n  top: 50%;\n  transform: translateX(-50%) translateY(-50%);\n  min-width: 600px;\n  min-height: 400px;\n  padding: 0;\n  border: 0;\n  position: fixed;\n  z-index: 11110;\n  display: block;\n  box-sizing: border-box;\n  background: #fff;\n  border-radius: 8px;\n  box-shadow: 0 6px 12px 0 rgba(106, 115, 133, 22%);\n  transition: transform 0.3s ease-in;\n  line-height: 14px;\n  font: 12px Helvetica Neue, Helvetica, Arial, Microsoft Yahei, Hiragino Sans GB,\n    Heiti SC, WenQuanYi Micro Hei, sans-serif;\n}\n.tool {\n  position: absolute;\n  border-bottom-left-radius: 8px;\n  border-bottom-right-radius: 8px;\n  overflow: hidden;\n  width: 100%;\n  display: inline-flex;\n  z-index: 1;\n  align-items: center;\n  justify-content: flex-end;\n  pointer-events: none;\n}\n.tool div {\n  border-radius: 50%;\n  padding: 10px;\n  transform: scale(0.8);\n  pointer-events: visible;\n}\n.tool div:hover {\n  background-color: rgba(0, 0, 0, 10%);\n}\n.content {\n  position: relative;\n  border-bottom-left-radius: 8px;\n  border-bottom-right-radius: 8px;\n  overflow: hidden;\n  background-color: #fff;\n}\n.contain {\n  padding-bottom: 15px;\n  background-position: top center;\n  background-size: contain;\n  background-repeat: no-repeat;\n  display: flex;\n  align-items: flex-start;\n  flex: 1;\n  height: 385px;\n}\n.menu::-webkit-scrollbar,\n.item::-webkit-scrollbar {\n  width: 0 !important;\n  height: 0 !important;\n}\n.menu {\n  flex: 1 1 0;\n  flex-basis: calc(480px * 0.2);\n  height: 100%;\n  position: sticky;\n  top: 0;\n  display: flex;\n  flex-direction: column;\n  min-width: fit-content;\n  overflow: auto;\n}\n.item {\n  flex: 4 4 0;\n  flex-basis: calc(480px * 0.8);\n  height: 100%;\n  box-sizing: border-box;\n  display: block;\n  margin: 0 auto;\n  position: relative;\n  overflow: auto;\n}\n.selected {\n  color: rgb(51, 103, 214) !important;\n}\n.selected > .icon {\n  fill: rgb(51, 103, 214) !important;\n}\n";
    modules["upList.css"] = ".up-info-m .up-card-box {\n  white-space: nowrap;\n  overflow: auto;\n}\n\n.up-info-m .up-card {\n  display: inline-block;\n  margin-top: 10px;\n}\n\n.up-info-m .avatar img {\n  cursor: pointer;\n  width: 40px;\n  height: 40px;\n  border-radius: 50%;\n}\n\n.up-info-m .avatar {\n  position: relative;\n}\n\n.up-info-m .avatar .info-tag {\n  position: absolute;\n  background: #fff;\n  border: 1px solid #fb7299;\n  border-radius: 2px;\n  display: inline-block;\n  font-size: 12px;\n  color: #fb7299;\n  padding: 0 3px;\n  top: -10px;\n  right: -10px;\n  white-space: nowrap;\n}\n\n.up-info-m .avatar {\n  width: 60px;\n  height: 30px;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-pack: center;\n  justify-content: center;\n  -ms-flex-align: start;\n  align-items: flex-start;\n}\n\n.up-info-m .avatar .name-text {\n  font-family: PingFangSC-Regular, sans-serif;\n  line-height: 30px;\n  color: #222;\n  word-break: break-all;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  display: -webkit-box;\n  -webkit-line-clamp: 2;\n  -webkit-box-orient: vertical;\n  white-space: nowrap;\n}\n\n.up-info-m .avatar .name-text.is-vip, .up-info-m .avatar .name-text:hover {\n  color: #fb7299;\n}\n\n.up-info-m .title {\n  display: block;\n  font-size: 14px;\n  margin-right: 80px;\n  color: #525659;\n  overflow: hidden;\n  height: 24px;\n  font-weight: 400;\n  padding: 8px 0;\n}";
    modules["anime.html"] = "<!DOCTYPE html>\n<html lang=\"zh-Hans\" xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"zh-Hans\">\n\n<head>\n    <meta charset=\"utf-8\" />\n    <title>番剧 - 哔哩哔哩 (゜-゜)つロ 干杯~-bilibili</title>\n    <meta name=\"description\" content=\"bilibili是国内知名的视频弹幕网站,这里有最及时的动漫新番,最棒的ACG氛围,最有创意的Up主。大家可以在这里找到许多欢乐。\" />\n    <meta name=\"keywords\" content=\"B站,弹幕,字幕,AMV,MAD,MTV,ANIME,动漫,动漫音乐,游戏,游戏解说,ACG,galgame,动画,番组,新番,初音,洛天依,vocaloid\" />\n    <meta name=\"renderer\" content=\"webkit\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta name=\"baidu-site-verification\" content=\"gbRdPloQBZ\" />\n    <link rel=\"dns-prefetch\" href=\"//s1.hdslb.com\" />\n    <link rel=\"dns-prefetch\" href=\"//s2.hdslb.com\" />\n    <link rel=\"dns-prefetch\" href=\"//s3.hdslb.com\" />\n    <link rel=\"dns-prefetch\" href=\"//i0.hdslb.com\" />\n    <link rel=\"dns-prefetch\" href=\"//i1.hdslb.com\" />\n    <link rel=\"dns-prefetch\" href=\"//i2.hdslb.com\" />\n    <link rel=\"dns-prefetch\" href=\"//static.hdslb.com\" />\n    <link rel=\"shortcut icon\" href=\"//static.hdslb.com/images/favicon.ico\" />\n    <link rel=\"search\" type=\"application/opensearchdescription+xml\" href=\"//static.hdslb.com/opensearch.xml\"\n        title=\"哔哩哔哩\" />\n    <script type=\"text/javascript\" src=\"//static.hdslb.com/js/jquery.min.js\"></script>\n    <script type=\"text/javascript\" src=\"//s1.hdslb.com/bfs/seed/jinkela/header/header.js\"></script>\n    <script type=\"text/javascript\" src=\"//s2.hdslb.com/bfs/cm/st/bundle.js\"></script>\n    <script type=\"text/javascript\" src=\"//static.hdslb.com/js/promise.auto.min.js\"></script>\n    <script type=\"text/javascript\"\n        src=\"//www.bilibili.com/gentleman/polyfill.js?features=Promise%2CObject.assign%2CString.prototype.includes%2CNumber.isNaN\"></script>\n    <script type=\"text/javascript\" src=\"//s1.hdslb.com/bfs/static/ogv/fe/iris.min.js\"></script>\n    <link rel=\"stylesheet\"\n        href=\"//s1.hdslb.com/bfs/static/bangumi-home/css/bangumi-home.1.73141fb5868615cb4fe6bc969ccd02cb7c1c7d4c.css\" />\n    <link rel=\"stylesheet\"\n        href=\"//s1.hdslb.com/bfs/static/bangumi-home/css/bangumi-home.0.73141fb5868615cb4fe6bc969ccd02cb7c1c7d4c.css\" />\n</head>\n\n<body>\n    <div class=\"z-top-container has-menu\"></div>\n    <div id=\"client-app\"></div>\n    <div id=\"app\" data-server-rendered=\"true\" class=\"cinema-home-wrapper\"></div>\n    <script src=\"//s1.hdslb.com/bfs/static/bangumi-home/1.bangumi-home.73141fb5868615cb4fe6bc969ccd02cb7c1c7d4c.js\"\n        crossorigin=\"\" defer=\"defer\"></script>\n    <script src=\"//s1.hdslb.com/bfs/static/bangumi-home/bangumi-home.73141fb5868615cb4fe6bc969ccd02cb7c1c7d4c.js\"\n        crossorigin=\"\" defer=\"defer\"></script>\n    <div class=\"footer bili-footer report-wrap-module\"></div>\n    <script type=\"text/javascript\" charset=\"utf-8\" src=\"//static.hdslb.com/common/js/footer.js\"></script>\n</body>\n\n</html>";
    modules["av.html"] = "<!DOCTYPE html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\n<head>\n  <meta charset=\"utf-8\" />\n  <title>哔哩哔哩 (゜-゜)つロ 干杯~-bilibili</title>\n  <meta name=\"description\" content=\"bilibili是国内知名的视频弹幕网站,这里有最及时的动漫新番,最棒的ACG氛围,最有创意的Up主。大家可以在这里找到许多欢乐。\" />\n  <meta name=\"keywords\"\n    content=\"Bilibili,哔哩哔哩,哔哩哔哩动画,哔哩哔哩弹幕网,弹幕视频,B站,弹幕,字幕,AMV,MAD,MTV,ANIME,动漫,动漫音乐,游戏,游戏解说,二次元,游戏视频,ACG,galgame,动画,番组,新番,初音,洛天依,vocaloid,日本动漫,国产动漫,手机游戏,网络游戏,电子竞技,ACG燃曲,ACG神曲,追新番,新番动漫,新番吐槽,巡音,镜音双子,千本樱,初音MIKU,舞蹈MMD,MIKUMIKUDANCE,洛天依原创曲,洛天依翻唱曲,洛天依投食歌,洛天依MMD,vocaloid家族,OST,BGM,动漫歌曲,日本动漫音乐,宫崎骏动漫音乐,动漫音乐推荐,燃系mad,治愈系mad,MAD MOVIE,MAD高燃\" />\n  <meta name=\"renderer\" content=\"webkit\" />\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n  <link rel=\"search\" type=\"application/opensearchdescription+xml\" href=\"//static.hdslb.com/opensearch.xml\"\n    title=\"哔哩哔哩\" />\n  <link rel=\"stylesheet\"\n    href=\"//s1.hdslb.com/bfs/static/jinkela/videoplay/css/video.0.406cee7878545872b8dfbe73071d665dfb287c67.css\" />\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/js/jquery.min.js\"></script>\n</head>\n\n<body>\n  <div class=\"z-top-container has-menu\"></div>\n  <div id=\"video-page-app\"></div>\n  <div id=\"app\" data-server-rendered=\"true\"></div>\n  <div class=\"bili-wrapper\" id=\"bofqi\"></div>\n  <div class=\"footer bili-footer report-wrap-module\"></div>\n  <script type=\"text/javascript\" src=\"//s1.hdslb.com/bfs/seed/jinkela/header/header.js\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/js/video.min.js\"></script>\n  <script type=\"text/javascript\">\n    function getQueryString(e) { var r = new RegExp(\"(^|&)\" + e + \"=([^&]*)(&|$)\"), i = window.location.search.substr(1).match(r); return null != i ? unescape(i[2]) : null } window.getInternetExplorerVersion = function () { var e = -1; if (\"Microsoft Internet Explorer\" == navigator.appName) { var r = navigator.userAgent; null != new RegExp(\"MSIE ([0-9]{1,}[.0-9]{0,})\").exec(r) && (e = parseFloat(RegExp.$1)) } return e }; var vd = window.__INITIAL_STATE__ && window.__INITIAL_STATE__.videoData; if (vd && vd.aid && 9 !== getInternetExplorerVersion()) { if ($(\"#__bofqi\").innerHTML = '<div class=\"bili-wrapper\" id=\"bofqi\"><div id=\"player_placeholder\"></div></div>', vd.embedPlayer) { var p = getQueryString(\"p\") ? getQueryString(\"p\") - 1 : 0, player = { aid: vd.aid, cid: vd.pages[p] && vd.pages[p].cid || vd.pages[0].cid }; EmbedPlayer(\"player\", \"//static.hdslb.com/play.swf\", \"cid=\" + player.cid + \"&aid=\" + player.aid + \"&pre_ad=\") } vd.embed && $(\"#bofqi\").html(vd.embed) } else $(\"#bofqi\").remove()\n  </script>\n  <script src=\"//s1.hdslb.com/bfs/static/jinkela/videoplay/manifest.b1b7706abd590dd295794f540f7669a5d8d978b3.js\"\n    crossorigin=\"\" defer=\"defer\"></script>\n  <script src=\"//s1.hdslb.com/bfs/static/jinkela/videoplay/vendor.b1b7706abd590dd295794f540f7669a5d8d978b3.js\"\n    crossorigin=\"\" defer=\"defer\"></script>\n  <script src=\"//s1.hdslb.com/bfs/static/jinkela/videoplay/video.b1b7706abd590dd295794f540f7669a5d8d978b3.js\"\n    crossorigin=\"\" defer=\"defer\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/phoenix/dist/js/comment.min.js\"></script>\n  <link rel=\"stylesheet\" href=\"//static.hdslb.com/phoenix/dist/css/comment.min.css\" type=\"text/css\" />\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/js/jquery.qrcode.min.js\"></script>\n  <script type=\"text/javascript\" charset=\"utf-8\" src=\"//static.hdslb.com/common/js/footer.js\"></script>\n</body>\n\n</html>";
    modules["bangumi-special.html"] = "<!DOCTYPE html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\n<head>\n    <meta charset=\"utf-8\" />\n    <title>哔哩哔哩 (゜-゜)つロ 干杯~-bilibili</title>\n    <meta name=\"description\" content=\"bilibili是国内知名的视频弹幕网站,这里有最及时的动漫新番,最棒的ACG氛围,最有创意的Up主。大家可以在这里找到许多欢乐。\" />\n    <meta name=\"keywords\"\n        content=\"Bilibili,哔哩哔哩,哔哩哔哩动画,哔哩哔哩弹幕网,弹幕视频,B站,弹幕,字幕,AMV,MAD,MTV,ANIME,动漫,动漫音乐,游戏,游戏解说,二次元,游戏视频,ACG,galgame,动画,番组,新番,初音,洛天依,vocaloid,日本动漫,国产动漫,手机游戏,网络游戏,电子竞技,ACG燃曲,ACG神曲,追新番,新番动漫,新番吐槽,巡音,镜音双子,千本樱,初音MIKU,舞蹈MMD,MIKUMIKUDANCE,洛天依原创曲,洛天依翻唱曲,洛天依投食歌,洛天依MMD,vocaloid家族,OST,BGM,动漫歌曲,日本动漫音乐,宫崎骏动漫音乐,动漫音乐推荐,燃系mad,治愈系mad,MAD MOVIE,MAD高燃\" />\n    <meta name=\"renderer\" content=\"webkit\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <link rel=\"search\" type=\"application/opensearchdescription+xml\" href=\"//static.hdslb.com/opensearch.xml\"\n        title=\"哔哩哔哩\" />\n    <link rel=\"stylesheet\" href=\"//static.hdslb.com/phoenix/dist/css/comment.min.css\" type=\"text/css\" />\n    <script type=\"text/javascript\" src=\"//static.hdslb.com/js/jquery.min.js\"></script>\n    <script type=\"text/javascript\" src=\"//static.hdslb.com/js/video.min.js\"></script>\n    <script type=\"text/javascript\" src=\"//static.hdslb.com/vip/dist/js/vipPlugin.v2.js\"></script>\n    <script type=\"text/javascript\" src=\"//static.hdslb.com/js/promise.auto.min.js\"></script>\n    <script type=\"text/javascript\" src=\"//s1.hdslb.com/bfs/seed/jinkela/header/header.js\"></script>\n    <link rel=\"stylesheet\"\n        href=\"//s1.hdslb.com/bfs/static/bangumi/play/css/bangumi-play.0.809bd6f6d1fba866255d2e6c5dc06dabba9ce8b4.css\" />\n</head>\n\n<body>\n    <div class=\"z-top-container\" style=\"height:42px\"></div>\n    <div id=\"app\" data-server-rendered=\"true\" class=\"main-container special\"></div>\n    <script src=\"//s1.hdslb.com/bfs/static/bangumi/play/1.bangumi-play.809bd6f6d1fba866255d2e6c5dc06dabba9ce8b4.js\"\n        crossorigin=\"\" defer=\"defer\"></script>\n    <script src=\"//s1.hdslb.com/bfs/static/bangumi/play/bangumi-play.809bd6f6d1fba866255d2e6c5dc06dabba9ce8b4.js\"\n        crossorigin=\"\" defer=\"defer\"></script>\n    <script type=\"text/javascript\" src=\"//static.hdslb.com/phoenix/dist/js/comment.min.js\"></script>\n    <div class=\"footer bili-footer report-wrap-module\" id=\"home_footer\"></div>\n    <script type=\"text/javascript\" src=\"//static.hdslb.com/common/js/footer.js\"></script>\n    <script src=\"//s1.hdslb.com/bfs/static/plugin/vip/BilAccountThaw.js\"></script>\n</body>\n\n</html>";
    modules["bangumi.html"] = "<!DOCTYPE html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\n<head>\n  <meta charset=\"utf-8\" />\n  <title>哔哩哔哩 (゜-゜)つロ 干杯~-bilibili</title>\n  <meta name=\"description\" content=\"bilibili是国内知名的视频弹幕网站,这里有最及时的动漫新番,最棒的ACG氛围,最有创意的Up主。大家可以在这里找到许多欢乐。\" />\n  <meta name=\"keywords\"\n    content=\"Bilibili,哔哩哔哩,哔哩哔哩动画,哔哩哔哩弹幕网,弹幕视频,B站,弹幕,字幕,AMV,MAD,MTV,ANIME,动漫,动漫音乐,游戏,游戏解说,二次元,游戏视频,ACG,galgame,动画,番组,新番,初音,洛天依,vocaloid,日本动漫,国产动漫,手机游戏,网络游戏,电子竞技,ACG燃曲,ACG神曲,追新番,新番动漫,新番吐槽,巡音,镜音双子,千本樱,初音MIKU,舞蹈MMD,MIKUMIKUDANCE,洛天依原创曲,洛天依翻唱曲,洛天依投食歌,洛天依MMD,vocaloid家族,OST,BGM,动漫歌曲,日本动漫音乐,宫崎骏动漫音乐,动漫音乐推荐,燃系mad,治愈系mad,MAD MOVIE,MAD高燃\" />\n  <meta name=\"renderer\" content=\"webkit\" />\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n  <link rel=\"search\" type=\"application/opensearchdescription+xml\" href=\"//static.hdslb.com/opensearch.xml\"\n    title=\"哔哩哔哩\" />\n  <link rel=\"stylesheet\" href=\"//static.hdslb.com/phoenix/dist/css/comment.min.css\" type=\"text/css\" />\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/js/jquery.min.js\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/js/video.min.js\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/vip/dist/js/vipPlugin.v2.js\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/js/promise.auto.min.js\"></script>\n  <script type=\"text/javascript\" src=\"//s1.hdslb.com/bfs/seed/jinkela/header/header.js\"></script>\n  <link rel=\"stylesheet\"\n    href=\"//s1.hdslb.com/bfs/static/bangumi/play/css/bangumi-play.0.809bd6f6d1fba866255d2e6c5dc06dabba9ce8b4.css\" />\n</head>\n\n<body>\n  <div class=\"z-top-container has-menu\"></div>\n  <div id=\"app\" data-server-rendered=\"true\" class=\"main-container\"></div>\n  <script src=\"//s1.hdslb.com/bfs/static/bangumi/play/1.bangumi-play.809bd6f6d1fba866255d2e6c5dc06dabba9ce8b4.js\"\n    crossorigin=\"\" defer=\"defer\"></script>\n  <script src=\"//s1.hdslb.com/bfs/static/bangumi/play/bangumi-play.809bd6f6d1fba866255d2e6c5dc06dabba9ce8b4.js\"\n    crossorigin=\"\" defer=\"defer\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/phoenix/dist/js/comment.min.js\"></script>\n  <div class=\"footer bili-footer report-wrap-module\" id=\"home_footer\"></div>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/common/js/footer.js\"></script>\n  <script src=\"//s1.hdslb.com/bfs/static/plugin/vip/BilAccountThaw.js\"></script>\n</body>\n\n</html>";
    modules["index.html"] = "<!DOCTYPE html>\n<html lang=\"zh-Hans\" xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"zh-Hans\">\n\n<head>\n  <meta charset=\"utf-8\" />\n  <title>哔哩哔哩 (゜-゜)つロ 干杯~-bilibili</title>\n  <meta name=\"description\" content=\"bilibili是国内知名的视频弹幕网站,这里有最及时的动漫新番,最棒的ACG氛围,最有创意的Up主。大家可以在这里找到许多欢乐。\" />\n  <meta name=\"keywords\"\n    content=\"Bilibili,哔哩哔哩,哔哩哔哩动画,哔哩哔哩弹幕网,弹幕视频,B站,弹幕,字幕,AMV,MAD,MTV,ANIME,动漫,动漫音乐,游戏,游戏解说,二次元,游戏视频,ACG,galgame,动画,番组,新番,初音,洛天依,vocaloid,日本动漫,国产动漫,手机游戏,网络游戏,电子竞技,ACG燃曲,ACG神曲,追新番,新番动漫,新番吐槽,巡音,镜音双子,千本樱,初音MIKU,舞蹈MMD,MIKUMIKUDANCE,洛天依原创曲,洛天依翻唱曲,洛天依投食歌,洛天依MMD,vocaloid家族,OST,BGM,动漫歌曲,日本动漫音乐,宫崎骏动漫音乐,动漫音乐推荐,燃系mad,治愈系mad,MAD MOVIE,MAD高燃\" />\n  <meta name=\"renderer\" content=\"webkit\" />\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n  <link rel=\"search\" type=\"application/opensearchdescription+xml\" href=\"//static.hdslb.com/opensearch.xml\"\n    title=\"哔哩哔哩\" />\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/js/jquery.min.js\"></script>\n  <link rel=\"stylesheet\"\n    href=\"//s1.hdslb.com/bfs/static/jinkela/home/css/home.0.4eadf4209b1762230047120e0a9945a9f3b56fd1.css\" />\n</head>\n\n<body>\n  <div id=\"home-app\"></div>\n  <div id=\"app\" data-server-rendered=\"true\"></div>\n  <script src=\"//s1.hdslb.com/bfs/seed/jinkela/header/header.js\"></script>\n  <script src=\"//s1.hdslb.com/bfs/static/jinkela/home/1.home.4eadf4209b1762230047120e0a9945a9f3b56fd1.js\"\n    defer=\"defer\"></script>\n  <script src=\"//s1.hdslb.com/bfs/static/jinkela/home/home.4eadf4209b1762230047120e0a9945a9f3b56fd1.js\"\n    defer=\"defer\"></script>\n  <div class=\"footer bili-footer report-wrap-module\"></div>\n  <script type=\"text/javascript\" src=\"//s1.hdslb.com/bfs/cm/st/bundle.js\" crossorigin=\"\"></script>\n  <script type=\"text/javascript\" defer=\"defer\" charset=\"utf-8\" src=\"//static.hdslb.com/common/js/footer.js\"></script>\n  <link rel=\"prefetch\" as=\"script\" href=\"//static.hdslb.com/js/video.min.js\" />\n</body>\n\n</html>";
    modules["player.html"] = "<!DOCTYPE html>\n<html>\n\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n    <meta name=\"viewport\"\n        content=\"target-densitydpi=device-dpi,width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,minimal-ui\">\n    <title>player - bilibili.com</title>\n    <script type=\"text/javascript\">\n        if (!!navigator.userAgent.match(/AppleWebKit.*Mobile.*/)) {\n            window.location.href = '//www.bilibili.com/blackboard/html5mobileplayer.html' + window.location.search;\n        }\n    </script>\n    <style type=\"text/css\">\n        html {\n            background-color: #fff;\n            font-family: \"Microsoft YaHei\", Arial, Helvetica, sans-serif;\n            overflow: hidden;\n        }\n\n        html,\n        body,\n        #bofqi,\n        .player {\n            width: 100%;\n            height: 100%;\n            margin: 0px;\n            padding: 0px;\n        }\n\n        #bofqi,\n        #bofqi .player-box {\n            width: 100%;\n            height: 100%;\n            overflow: visible;\n            box-sizing: border-box;\n        }\n\n        #bofqi object {\n            width: 100%;\n            height: 100%;\n        }\n\n        #dm_send_bar {\n            width: 100%;\n            height: 60px;\n            position: absolute;\n            bottom: -60px;\n            background-color: transparent;\n        }\n\n        #dm_send_input {\n            margin: 10px 0 10px 2%;\n            height: 40px;\n            line-height: 38px;\n            border: 1px solid #ddd;\n            border-radius: 5px;\n            font-size: 1rem;\n            font-family: \"Microsoft YaHei\";\n            padding: 0 8px;\n            width: 70%;\n            outline: 0;\n            box-sizing: border-box;\n            color: #333;\n        }\n\n        #dm_send_btn {\n            height: 40px;\n            line-height: 40px;\n            font-size: 1rem;\n            color: #fff;\n            background: #de698c;\n            border-radius: 6px;\n            margin: 10px 3% 10px 0;\n            width: 20%;\n            box-sizing: border-box;\n            outline: 0;\n            border: 0;\n            float: right;\n        }\n\n        #dm_send_btn:focus,\n        #dm_send_btn.disabled {\n            background-color: #b65673;\n        }\n    </style>\n</head>\n\n<body>\n    <div id=\"bofqi\"></div>\n    <script type=\"text/javascript\" src=\"//static.hdslb.com/js/jquery.min.js\"></script>\n    <script type=\"text/javascript\" src=\"//static.hdslb.com/js/jquery.qrcode.min.js\"></script>\n    <script type=\"text/javascript\" src=\"//static.hdslb.com/player/js/whitelist.js\"></script>\n    <script type=\"text/javascript\">\n        /* == jquery mousewheel plugin == Version: 3.1.13, License: MIT License (MIT) */\n        !function (a) { \"function\" == typeof define && define.amd ? define([\"jquery\"], a) : \"object\" == typeof exports ? module.exports = a : a(jQuery) }(function (a) { function b(b) { var g = b || window.event, h = i.call(arguments, 1), j = 0, l = 0, m = 0, n = 0, o = 0, p = 0; if (b = a.event.fix(g), b.type = \"mousewheel\", \"detail\" in g && (m = -1 * g.detail), \"wheelDelta\" in g && (m = g.wheelDelta), \"wheelDeltaY\" in g && (m = g.wheelDeltaY), \"wheelDeltaX\" in g && (l = -1 * g.wheelDeltaX), \"axis\" in g && g.axis === g.HORIZONTAL_AXIS && (l = -1 * m, m = 0), j = 0 === m ? l : m, \"deltaY\" in g && (m = -1 * g.deltaY, j = m), \"deltaX\" in g && (l = g.deltaX, 0 === m && (j = -1 * l)), 0 !== m || 0 !== l) { if (1 === g.deltaMode) { var q = a.data(this, \"mousewheel-line-height\"); j *= q, m *= q, l *= q } else if (2 === g.deltaMode) { var r = a.data(this, \"mousewheel-page-height\"); j *= r, m *= r, l *= r } if (n = Math.max(Math.abs(m), Math.abs(l)), (!f || f > n) && (f = n, d(g, n) && (f /= 40)), d(g, n) && (j /= 40, l /= 40, m /= 40), j = Math[j >= 1 ? \"floor\" : \"ceil\"](j / f), l = Math[l >= 1 ? \"floor\" : \"ceil\"](l / f), m = Math[m >= 1 ? \"floor\" : \"ceil\"](m / f), k.settings.normalizeOffset && this.getBoundingClientRect) { var s = this.getBoundingClientRect(); o = b.clientX - s.left, p = b.clientY - s.top } return b.deltaX = l, b.deltaY = m, b.deltaFactor = f, b.offsetX = o, b.offsetY = p, b.deltaMode = 0, h.unshift(b, j, l, m), e && clearTimeout(e), e = setTimeout(c, 200), (a.event.dispatch || a.event.handle).apply(this, h) } } function c() { f = null } function d(a, b) { return k.settings.adjustOldDeltas && \"mousewheel\" === a.type && b % 120 === 0 } var e, f, g = [\"wheel\", \"mousewheel\", \"DOMMouseScroll\", \"MozMousePixelScroll\"], h = \"onwheel\" in document || document.documentMode >= 9 ? [\"wheel\"] : [\"mousewheel\", \"DomMouseScroll\", \"MozMousePixelScroll\"], i = Array.prototype.slice; if (a.event.fixHooks) for (var j = g.length; j;)a.event.fixHooks[g[--j]] = a.event.mouseHooks; var k = a.event.special.mousewheel = { version: \"3.1.12\", setup: function () { if (this.addEventListener) for (var c = h.length; c;)this.addEventListener(h[--c], b, !1); else this.onmousewheel = b; a.data(this, \"mousewheel-line-height\", k.getLineHeight(this)), a.data(this, \"mousewheel-page-height\", k.getPageHeight(this)) }, teardown: function () { if (this.removeEventListener) for (var c = h.length; c;)this.removeEventListener(h[--c], b, !1); else this.onmousewheel = null; a.removeData(this, \"mousewheel-line-height\"), a.removeData(this, \"mousewheel-page-height\") }, getLineHeight: function (b) { var c = a(b), d = c[\"offsetParent\" in a.fn ? \"offsetParent\" : \"parent\"](); return d.length || (d = a(\"body\")), parseInt(d.css(\"fontSize\"), 10) || parseInt(c.css(\"fontSize\"), 10) || 16 }, getPageHeight: function (b) { return a(b).height() }, settings: { adjustOldDeltas: !0, normalizeOffset: !0 } }; a.fn.extend({ mousewheel: function (a) { return a ? this.bind(\"mousewheel\", a) : this.trigger(\"mousewheel\") }, unmousewheel: function (a) { return this.unbind(\"mousewheel\", a) } }) }); !function (a) { \"function\" == typeof define && define.amd ? define([\"jquery\"], a) : \"object\" == typeof exports ? module.exports = a : a(jQuery) }(function (a) { function b(b) { var g = b || window.event, h = i.call(arguments, 1), j = 0, l = 0, m = 0, n = 0, o = 0, p = 0; if (b = a.event.fix(g), b.type = \"mousewheel\", \"detail\" in g && (m = -1 * g.detail), \"wheelDelta\" in g && (m = g.wheelDelta), \"wheelDeltaY\" in g && (m = g.wheelDeltaY), \"wheelDeltaX\" in g && (l = -1 * g.wheelDeltaX), \"axis\" in g && g.axis === g.HORIZONTAL_AXIS && (l = -1 * m, m = 0), j = 0 === m ? l : m, \"deltaY\" in g && (m = -1 * g.deltaY, j = m), \"deltaX\" in g && (l = g.deltaX, 0 === m && (j = -1 * l)), 0 !== m || 0 !== l) { if (1 === g.deltaMode) { var q = a.data(this, \"mousewheel-line-height\"); j *= q, m *= q, l *= q } else if (2 === g.deltaMode) { var r = a.data(this, \"mousewheel-page-height\"); j *= r, m *= r, l *= r } if (n = Math.max(Math.abs(m), Math.abs(l)), (!f || f > n) && (f = n, d(g, n) && (f /= 40)), d(g, n) && (j /= 40, l /= 40, m /= 40), j = Math[j >= 1 ? \"floor\" : \"ceil\"](j / f), l = Math[l >= 1 ? \"floor\" : \"ceil\"](l / f), m = Math[m >= 1 ? \"floor\" : \"ceil\"](m / f), k.settings.normalizeOffset && this.getBoundingClientRect) { var s = this.getBoundingClientRect(); o = b.clientX - s.left, p = b.clientY - s.top } return b.deltaX = l, b.deltaY = m, b.deltaFactor = f, b.offsetX = o, b.offsetY = p, b.deltaMode = 0, h.unshift(b, j, l, m), e && clearTimeout(e), e = setTimeout(c, 200), (a.event.dispatch || a.event.handle).apply(this, h) } } function c() { f = null } function d(a, b) { return k.settings.adjustOldDeltas && \"mousewheel\" === a.type && b % 120 === 0 } var e, f, g = [\"wheel\", \"mousewheel\", \"DOMMouseScroll\", \"MozMousePixelScroll\"], h = \"onwheel\" in document || document.documentMode >= 9 ? [\"wheel\"] : [\"mousewheel\", \"DomMouseScroll\", \"MozMousePixelScroll\"], i = Array.prototype.slice; if (a.event.fixHooks) for (var j = g.length; j;)a.event.fixHooks[g[--j]] = a.event.mouseHooks; var k = a.event.special.mousewheel = { version: \"3.1.12\", setup: function () { if (this.addEventListener) for (var c = h.length; c;)this.addEventListener(h[--c], b, !1); else this.onmousewheel = b; a.data(this, \"mousewheel-line-height\", k.getLineHeight(this)), a.data(this, \"mousewheel-page-height\", k.getPageHeight(this)) }, teardown: function () { if (this.removeEventListener) for (var c = h.length; c;)this.removeEventListener(h[--c], b, !1); else this.onmousewheel = null; a.removeData(this, \"mousewheel-line-height\"), a.removeData(this, \"mousewheel-page-height\") }, getLineHeight: function (b) { var c = a(b), d = c[\"offsetParent\" in a.fn ? \"offsetParent\" : \"parent\"](); return d.length || (d = a(\"body\")), parseInt(d.css(\"fontSize\"), 10) || parseInt(c.css(\"fontSize\"), 10) || 16 }, getPageHeight: function (b) { return a(b).height() }, settings: { adjustOldDeltas: !0, normalizeOffset: !0 } }; a.fn.extend({ mousewheel: function (a) { return a ? this.bind(\"mousewheel\", a) : this.trigger(\"mousewheel\") }, unmousewheel: function (a) { return this.unbind(\"mousewheel\", a) } }) });\n        /* == malihu jquery custom scrollbar plugin == Version: 3.1.5, License: MIT License (MIT) */\n        !function (e) { \"function\" == typeof define && define.amd ? define([\"jquery\"], e) : \"undefined\" != typeof module && module.exports ? module.exports = e : e(jQuery, window, document) }(function (e) {\n            !function (t) { var o = \"function\" == typeof define && define.amd, a = \"undefined\" != typeof module && module.exports, n = \"https:\" == document.location.protocol ? \"https:\" : \"http:\", i = \"cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js\"; o || (a ? require(\"jquery-mousewheel\")(e) : e.event.special.mousewheel || e(\"head\").append(decodeURI(\"%3Cscript src=\" + n + \"//\" + i + \"%3E%3C/script%3E\"))), t() }(function () {\n                var t, o = \"mCustomScrollbar\", a = \"mCS\", n = \".mCustomScrollbar\", i = { setTop: 0, setLeft: 0, axis: \"y\", scrollbarPosition: \"inside\", scrollInertia: 950, autoDraggerLength: !0, alwaysShowScrollbar: 0, snapOffset: 0, mouseWheel: { enable: !0, scrollAmount: \"auto\", axis: \"y\", deltaFactor: \"auto\", disableOver: [\"select\", \"option\", \"keygen\", \"datalist\", \"textarea\"] }, scrollButtons: { scrollType: \"stepless\", scrollAmount: \"auto\" }, keyboard: { enable: !0, scrollType: \"stepless\", scrollAmount: \"auto\" }, contentTouchScroll: 25, documentTouchScroll: !0, advanced: { autoScrollOnFocus: \"input,textarea,select,button,datalist,keygen,a[tabindex],area,object,[contenteditable='true']\", updateOnContentResize: !0, updateOnImageLoad: \"auto\", autoUpdateTimeout: 60 }, theme: \"light\", callbacks: { onTotalScrollOffset: 0, onTotalScrollBackOffset: 0, alwaysTriggerOffsets: !0 } }, r = 0, l = {}, s = window.attachEvent && !window.addEventListener ? 1 : 0, c = !1, d = [\"mCSB_dragger_onDrag\", \"mCSB_scrollTools_onDrag\", \"mCS_img_loaded\", \"mCS_disabled\", \"mCS_destroyed\", \"mCS_no_scrollbar\", \"mCS-autoHide\", \"mCS-dir-rtl\", \"mCS_no_scrollbar_y\", \"mCS_no_scrollbar_x\", \"mCS_y_hidden\", \"mCS_x_hidden\", \"mCSB_draggerContainer\", \"mCSB_buttonUp\", \"mCSB_buttonDown\", \"mCSB_buttonLeft\", \"mCSB_buttonRight\"], u = { init: function (t) { var t = e.extend(!0, {}, i, t), o = f.call(this); if (t.live) { var s = t.liveSelector || this.selector || n, c = e(s); if (\"off\" === t.live) return void m(s); l[s] = setTimeout(function () { c.mCustomScrollbar(t), \"once\" === t.live && c.length && m(s) }, 500) } else m(s); return t.setWidth = t.set_width ? t.set_width : t.setWidth, t.setHeight = t.set_height ? t.set_height : t.setHeight, t.axis = t.horizontalScroll ? \"x\" : p(t.axis), t.scrollInertia = t.scrollInertia > 0 && t.scrollInertia < 17 ? 17 : t.scrollInertia, \"object\" != typeof t.mouseWheel && 1 == t.mouseWheel && (t.mouseWheel = { enable: !0, scrollAmount: \"auto\", axis: \"y\", preventDefault: !1, deltaFactor: \"auto\", normalizeDelta: !1, invert: !1 }), t.mouseWheel.scrollAmount = t.mouseWheelPixels ? t.mouseWheelPixels : t.mouseWheel.scrollAmount, t.mouseWheel.normalizeDelta = t.advanced.normalizeMouseWheelDelta ? t.advanced.normalizeMouseWheelDelta : t.mouseWheel.normalizeDelta, t.scrollButtons.scrollType = g(t.scrollButtons.scrollType), h(t), e(o).each(function () { var o = e(this); if (!o.data(a)) { o.data(a, { idx: ++r, opt: t, scrollRatio: { y: null, x: null }, overflowed: null, contentReset: { y: null, x: null }, bindEvents: !1, tweenRunning: !1, sequential: {}, langDir: o.css(\"direction\"), cbOffsets: null, trigger: null, poll: { size: { o: 0, n: 0 }, img: { o: 0, n: 0 }, change: { o: 0, n: 0 } } }); var n = o.data(a), i = n.opt, l = o.data(\"mcs-axis\"), s = o.data(\"mcs-scrollbar-position\"), c = o.data(\"mcs-theme\"); l && (i.axis = l), s && (i.scrollbarPosition = s), c && (i.theme = c, h(i)), v.call(this), n && i.callbacks.onCreate && \"function\" == typeof i.callbacks.onCreate && i.callbacks.onCreate.call(this), e(\"#mCSB_\" + n.idx + \"_container img:not(.\" + d[2] + \")\").addClass(d[2]), u.update.call(null, o) } }) }, update: function (t, o) { var n = t || f.call(this); return e(n).each(function () { var t = e(this); if (t.data(a)) { var n = t.data(a), i = n.opt, r = e(\"#mCSB_\" + n.idx + \"_container\"), l = e(\"#mCSB_\" + n.idx), s = [e(\"#mCSB_\" + n.idx + \"_dragger_vertical\"), e(\"#mCSB_\" + n.idx + \"_dragger_horizontal\")]; if (!r.length) return; n.tweenRunning && Q(t), o && n && i.callbacks.onBeforeUpdate && \"function\" == typeof i.callbacks.onBeforeUpdate && i.callbacks.onBeforeUpdate.call(this), t.hasClass(d[3]) && t.removeClass(d[3]), t.hasClass(d[4]) && t.removeClass(d[4]), l.css(\"max-height\", \"none\"), l.height() !== t.height() && l.css(\"max-height\", t.height()), _.call(this), \"y\" === i.axis || i.advanced.autoExpandHorizontalScroll || r.css(\"width\", x(r)), n.overflowed = y.call(this), M.call(this), i.autoDraggerLength && S.call(this), b.call(this), T.call(this); var c = [Math.abs(r[0].offsetTop), Math.abs(r[0].offsetLeft)]; \"x\" !== i.axis && (n.overflowed[0] ? s[0].height() > s[0].parent().height() ? B.call(this) : (G(t, c[0].toString(), { dir: \"y\", dur: 0, overwrite: \"none\" }), n.contentReset.y = null) : (B.call(this), \"y\" === i.axis ? k.call(this) : \"yx\" === i.axis && n.overflowed[1] && G(t, c[1].toString(), { dir: \"x\", dur: 0, overwrite: \"none\" }))), \"y\" !== i.axis && (n.overflowed[1] ? s[1].width() > s[1].parent().width() ? B.call(this) : (G(t, c[1].toString(), { dir: \"x\", dur: 0, overwrite: \"none\" }), n.contentReset.x = null) : (B.call(this), \"x\" === i.axis ? k.call(this) : \"yx\" === i.axis && n.overflowed[0] && G(t, c[0].toString(), { dir: \"y\", dur: 0, overwrite: \"none\" }))), o && n && (2 === o && i.callbacks.onImageLoad && \"function\" == typeof i.callbacks.onImageLoad ? i.callbacks.onImageLoad.call(this) : 3 === o && i.callbacks.onSelectorChange && \"function\" == typeof i.callbacks.onSelectorChange ? i.callbacks.onSelectorChange.call(this) : i.callbacks.onUpdate && \"function\" == typeof i.callbacks.onUpdate && i.callbacks.onUpdate.call(this)), N.call(this) } }) }, scrollTo: function (t, o) { if (\"undefined\" != typeof t && null != t) { var n = f.call(this); return e(n).each(function () { var n = e(this); if (n.data(a)) { var i = n.data(a), r = i.opt, l = { trigger: \"external\", scrollInertia: r.scrollInertia, scrollEasing: \"mcsEaseInOut\", moveDragger: !1, timeout: 60, callbacks: !0, onStart: !0, onUpdate: !0, onComplete: !0 }, s = e.extend(!0, {}, l, o), c = Y.call(this, t), d = s.scrollInertia > 0 && s.scrollInertia < 17 ? 17 : s.scrollInertia; c[0] = X.call(this, c[0], \"y\"), c[1] = X.call(this, c[1], \"x\"), s.moveDragger && (c[0] *= i.scrollRatio.y, c[1] *= i.scrollRatio.x), s.dur = ne() ? 0 : d, setTimeout(function () { null !== c[0] && \"undefined\" != typeof c[0] && \"x\" !== r.axis && i.overflowed[0] && (s.dir = \"y\", s.overwrite = \"all\", G(n, c[0].toString(), s)), null !== c[1] && \"undefined\" != typeof c[1] && \"y\" !== r.axis && i.overflowed[1] && (s.dir = \"x\", s.overwrite = \"none\", G(n, c[1].toString(), s)) }, s.timeout) } }) } }, stop: function () { var t = f.call(this); return e(t).each(function () { var t = e(this); t.data(a) && Q(t) }) }, disable: function (t) { var o = f.call(this); return e(o).each(function () { var o = e(this); if (o.data(a)) { o.data(a); N.call(this, \"remove\"), k.call(this), t && B.call(this), M.call(this, !0), o.addClass(d[3]) } }) }, destroy: function () { var t = f.call(this); return e(t).each(function () { var n = e(this); if (n.data(a)) { var i = n.data(a), r = i.opt, l = e(\"#mCSB_\" + i.idx), s = e(\"#mCSB_\" + i.idx + \"_container\"), c = e(\".mCSB_\" + i.idx + \"_scrollbar\"); r.live && m(r.liveSelector || e(t).selector), N.call(this, \"remove\"), k.call(this), B.call(this), n.removeData(a), $(this, \"mcs\"), c.remove(), s.find(\"img.\" + d[2]).removeClass(d[2]), l.replaceWith(s.contents()), n.removeClass(o + \" _\" + a + \"_\" + i.idx + \" \" + d[6] + \" \" + d[7] + \" \" + d[5] + \" \" + d[3]).addClass(d[4]) } }) } }, f = function () { return \"object\" != typeof e(this) || e(this).length < 1 ? n : this }, h = function (t) { var o = [\"rounded\", \"rounded-dark\", \"rounded-dots\", \"rounded-dots-dark\"], a = [\"rounded-dots\", \"rounded-dots-dark\", \"3d\", \"3d-dark\", \"3d-thick\", \"3d-thick-dark\", \"inset\", \"inset-dark\", \"inset-2\", \"inset-2-dark\", \"inset-3\", \"inset-3-dark\"], n = [\"minimal\", \"minimal-dark\"], i = [\"minimal\", \"minimal-dark\"], r = [\"minimal\", \"minimal-dark\"]; t.autoDraggerLength = e.inArray(t.theme, o) > -1 ? !1 : t.autoDraggerLength, t.autoExpandScrollbar = e.inArray(t.theme, a) > -1 ? !1 : t.autoExpandScrollbar, t.scrollButtons.enable = e.inArray(t.theme, n) > -1 ? !1 : t.scrollButtons.enable, t.autoHideScrollbar = e.inArray(t.theme, i) > -1 ? !0 : t.autoHideScrollbar, t.scrollbarPosition = e.inArray(t.theme, r) > -1 ? \"outside\" : t.scrollbarPosition }, m = function (e) { l[e] && (clearTimeout(l[e]), $(l, e)) }, p = function (e) { return \"yx\" === e || \"xy\" === e || \"auto\" === e ? \"yx\" : \"x\" === e || \"horizontal\" === e ? \"x\" : \"y\" }, g = function (e) { return \"stepped\" === e || \"pixels\" === e || \"step\" === e || \"click\" === e ? \"stepped\" : \"stepless\" }, v = function () { var t = e(this), n = t.data(a), i = n.opt, r = i.autoExpandScrollbar ? \" \" + d[1] + \"_expand\" : \"\", l = [\"<div id='mCSB_\" + n.idx + \"_scrollbar_vertical' class='mCSB_scrollTools mCSB_\" + n.idx + \"_scrollbar mCS-\" + i.theme + \" mCSB_scrollTools_vertical\" + r + \"'><div class='\" + d[12] + \"'><div id='mCSB_\" + n.idx + \"_dragger_vertical' class='mCSB_dragger' style='position:absolute;'><div class='mCSB_dragger_bar' /></div><div class='mCSB_draggerRail' /></div></div>\", \"<div id='mCSB_\" + n.idx + \"_scrollbar_horizontal' class='mCSB_scrollTools mCSB_\" + n.idx + \"_scrollbar mCS-\" + i.theme + \" mCSB_scrollTools_horizontal\" + r + \"'><div class='\" + d[12] + \"'><div id='mCSB_\" + n.idx + \"_dragger_horizontal' class='mCSB_dragger' style='position:absolute;'><div class='mCSB_dragger_bar' /></div><div class='mCSB_draggerRail' /></div></div>\"], s = \"yx\" === i.axis ? \"mCSB_vertical_horizontal\" : \"x\" === i.axis ? \"mCSB_horizontal\" : \"mCSB_vertical\", c = \"yx\" === i.axis ? l[0] + l[1] : \"x\" === i.axis ? l[1] : l[0], u = \"yx\" === i.axis ? \"<div id='mCSB_\" + n.idx + \"_container_wrapper' class='mCSB_container_wrapper' />\" : \"\", f = i.autoHideScrollbar ? \" \" + d[6] : \"\", h = \"x\" !== i.axis && \"rtl\" === n.langDir ? \" \" + d[7] : \"\"; i.setWidth && t.css(\"width\", i.setWidth), i.setHeight && t.css(\"height\", i.setHeight), i.setLeft = \"y\" !== i.axis && \"rtl\" === n.langDir ? \"989999px\" : i.setLeft, t.addClass(o + \" _\" + a + \"_\" + n.idx + f + h).wrapInner(\"<div id='mCSB_\" + n.idx + \"' class='mCustomScrollBox mCS-\" + i.theme + \" \" + s + \"'><div id='mCSB_\" + n.idx + \"_container' class='mCSB_container' style='position:relative; top:\" + i.setTop + \"; left:\" + i.setLeft + \";' dir='\" + n.langDir + \"' /></div>\"); var m = e(\"#mCSB_\" + n.idx), p = e(\"#mCSB_\" + n.idx + \"_container\"); \"y\" === i.axis || i.advanced.autoExpandHorizontalScroll || p.css(\"width\", x(p)), \"outside\" === i.scrollbarPosition ? (\"static\" === t.css(\"position\") && t.css(\"position\", \"relative\"), t.css(\"overflow\", \"visible\"), m.addClass(\"mCSB_outside\").after(c)) : (m.addClass(\"mCSB_inside\").append(c), p.wrap(u)), w.call(this); var g = [e(\"#mCSB_\" + n.idx + \"_dragger_vertical\"), e(\"#mCSB_\" + n.idx + \"_dragger_horizontal\")]; g[0].css(\"min-height\", g[0].height()), g[1].css(\"min-width\", g[1].width()) }, x = function (t) { var o = [t[0].scrollWidth, Math.max.apply(Math, t.children().map(function () { return e(this).outerWidth(!0) }).get())], a = t.parent().width(); return o[0] > a ? o[0] : o[1] > a ? o[1] : \"100%\" }, _ = function () { var t = e(this), o = t.data(a), n = o.opt, i = e(\"#mCSB_\" + o.idx + \"_container\"); if (n.advanced.autoExpandHorizontalScroll && \"y\" !== n.axis) { i.css({ width: \"auto\", \"min-width\": 0, \"overflow-x\": \"scroll\" }); var r = Math.ceil(i[0].scrollWidth); 3 === n.advanced.autoExpandHorizontalScroll || 2 !== n.advanced.autoExpandHorizontalScroll && r > i.parent().width() ? i.css({ width: r, \"min-width\": \"100%\", \"overflow-x\": \"inherit\" }) : i.css({ \"overflow-x\": \"inherit\", position: \"absolute\" }).wrap(\"<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />\").css({ width: Math.ceil(i[0].getBoundingClientRect().right + .4) - Math.floor(i[0].getBoundingClientRect().left), \"min-width\": \"100%\", position: \"relative\" }).unwrap() } }, w = function () { var t = e(this), o = t.data(a), n = o.opt, i = e(\".mCSB_\" + o.idx + \"_scrollbar:first\"), r = oe(n.scrollButtons.tabindex) ? \"tabindex='\" + n.scrollButtons.tabindex + \"'\" : \"\", l = [\"<a href='#' class='\" + d[13] + \"' \" + r + \" />\", \"<a href='#' class='\" + d[14] + \"' \" + r + \" />\", \"<a href='#' class='\" + d[15] + \"' \" + r + \" />\", \"<a href='#' class='\" + d[16] + \"' \" + r + \" />\"], s = [\"x\" === n.axis ? l[2] : l[0], \"x\" === n.axis ? l[3] : l[1], l[2], l[3]]; n.scrollButtons.enable && i.prepend(s[0]).append(s[1]).next(\".mCSB_scrollTools\").prepend(s[2]).append(s[3]) }, S = function () { var t = e(this), o = t.data(a), n = e(\"#mCSB_\" + o.idx), i = e(\"#mCSB_\" + o.idx + \"_container\"), r = [e(\"#mCSB_\" + o.idx + \"_dragger_vertical\"), e(\"#mCSB_\" + o.idx + \"_dragger_horizontal\")], l = [n.height() / i.outerHeight(!1), n.width() / i.outerWidth(!1)], c = [parseInt(r[0].css(\"min-height\")), Math.round(l[0] * r[0].parent().height()), parseInt(r[1].css(\"min-width\")), Math.round(l[1] * r[1].parent().width())], d = s && c[1] < c[0] ? c[0] : c[1], u = s && c[3] < c[2] ? c[2] : c[3]; r[0].css({ height: d, \"max-height\": r[0].parent().height() - 10 }).find(\".mCSB_dragger_bar\").css({ \"line-height\": c[0] + \"px\" }), r[1].css({ width: u, \"max-width\": r[1].parent().width() - 10 }) }, b = function () { var t = e(this), o = t.data(a), n = e(\"#mCSB_\" + o.idx), i = e(\"#mCSB_\" + o.idx + \"_container\"), r = [e(\"#mCSB_\" + o.idx + \"_dragger_vertical\"), e(\"#mCSB_\" + o.idx + \"_dragger_horizontal\")], l = [i.outerHeight(!1) - n.height(), i.outerWidth(!1) - n.width()], s = [l[0] / (r[0].parent().height() - r[0].height()), l[1] / (r[1].parent().width() - r[1].width())]; o.scrollRatio = { y: s[0], x: s[1] } }, C = function (e, t, o) { var a = o ? d[0] + \"_expanded\" : \"\", n = e.closest(\".mCSB_scrollTools\"); \"active\" === t ? (e.toggleClass(d[0] + \" \" + a), n.toggleClass(d[1]), e[0]._draggable = e[0]._draggable ? 0 : 1) : e[0]._draggable || (\"hide\" === t ? (e.removeClass(d[0]), n.removeClass(d[1])) : (e.addClass(d[0]), n.addClass(d[1]))) }, y = function () { var t = e(this), o = t.data(a), n = e(\"#mCSB_\" + o.idx), i = e(\"#mCSB_\" + o.idx + \"_container\"), r = null == o.overflowed ? i.height() : i.outerHeight(!1), l = null == o.overflowed ? i.width() : i.outerWidth(!1), s = i[0].scrollHeight, c = i[0].scrollWidth; return s > r && (r = s), c > l && (l = c), [r > n.height(), l > n.width()] }, B = function () { var t = e(this), o = t.data(a), n = o.opt, i = e(\"#mCSB_\" + o.idx), r = e(\"#mCSB_\" + o.idx + \"_container\"), l = [e(\"#mCSB_\" + o.idx + \"_dragger_vertical\"), e(\"#mCSB_\" + o.idx + \"_dragger_horizontal\")]; if (Q(t), (\"x\" !== n.axis && !o.overflowed[0] || \"y\" === n.axis && o.overflowed[0]) && (l[0].add(r).css(\"top\", 0), G(t, \"_resetY\")), \"y\" !== n.axis && !o.overflowed[1] || \"x\" === n.axis && o.overflowed[1]) { var s = dx = 0; \"rtl\" === o.langDir && (s = i.width() - r.outerWidth(!1), dx = Math.abs(s / o.scrollRatio.x)), r.css(\"left\", s), l[1].css(\"left\", dx), G(t, \"_resetX\") } }, T = function () { function t() { r = setTimeout(function () { e.event.special.mousewheel ? (clearTimeout(r), W.call(o[0])) : t() }, 100) } var o = e(this), n = o.data(a), i = n.opt; if (!n.bindEvents) { if (I.call(this), i.contentTouchScroll && D.call(this), E.call(this), i.mouseWheel.enable) { var r; t() } P.call(this), U.call(this), i.advanced.autoScrollOnFocus && H.call(this), i.scrollButtons.enable && F.call(this), i.keyboard.enable && q.call(this), n.bindEvents = !0 } }, k = function () { var t = e(this), o = t.data(a), n = o.opt, i = a + \"_\" + o.idx, r = \".mCSB_\" + o.idx + \"_scrollbar\", l = e(\"#mCSB_\" + o.idx + \",#mCSB_\" + o.idx + \"_container,#mCSB_\" + o.idx + \"_container_wrapper,\" + r + \" .\" + d[12] + \",#mCSB_\" + o.idx + \"_dragger_vertical,#mCSB_\" + o.idx + \"_dragger_horizontal,\" + r + \">a\"), s = e(\"#mCSB_\" + o.idx + \"_container\"); n.advanced.releaseDraggableSelectors && l.add(e(n.advanced.releaseDraggableSelectors)), n.advanced.extraDraggableSelectors && l.add(e(n.advanced.extraDraggableSelectors)), o.bindEvents && (e(document).add(e(!A() || top.document)).unbind(\".\" + i), l.each(function () { e(this).unbind(\".\" + i) }), clearTimeout(t[0]._focusTimeout), $(t[0], \"_focusTimeout\"), clearTimeout(o.sequential.step), $(o.sequential, \"step\"), clearTimeout(s[0].onCompleteTimeout), $(s[0], \"onCompleteTimeout\"), o.bindEvents = !1) }, M = function (t) { var o = e(this), n = o.data(a), i = n.opt, r = e(\"#mCSB_\" + n.idx + \"_container_wrapper\"), l = r.length ? r : e(\"#mCSB_\" + n.idx + \"_container\"), s = [e(\"#mCSB_\" + n.idx + \"_scrollbar_vertical\"), e(\"#mCSB_\" + n.idx + \"_scrollbar_horizontal\")], c = [s[0].find(\".mCSB_dragger\"), s[1].find(\".mCSB_dragger\")]; \"x\" !== i.axis && (n.overflowed[0] && !t ? (s[0].add(c[0]).add(s[0].children(\"a\")).css(\"display\", \"block\"), l.removeClass(d[8] + \" \" + d[10])) : (i.alwaysShowScrollbar ? (2 !== i.alwaysShowScrollbar && c[0].css(\"display\", \"none\"), l.removeClass(d[10])) : (s[0].css(\"display\", \"none\"), l.addClass(d[10])), l.addClass(d[8]))), \"y\" !== i.axis && (n.overflowed[1] && !t ? (s[1].add(c[1]).add(s[1].children(\"a\")).css(\"display\", \"block\"), l.removeClass(d[9] + \" \" + d[11])) : (i.alwaysShowScrollbar ? (2 !== i.alwaysShowScrollbar && c[1].css(\"display\", \"none\"), l.removeClass(d[11])) : (s[1].css(\"display\", \"none\"), l.addClass(d[11])), l.addClass(d[9]))), n.overflowed[0] || n.overflowed[1] ? o.removeClass(d[5]) : o.addClass(d[5]) }, O = function (t) { var o = t.type, a = t.target.ownerDocument !== document && null !== frameElement ? [e(frameElement).offset().top, e(frameElement).offset().left] : null, n = A() && t.target.ownerDocument !== top.document && null !== frameElement ? [e(t.view.frameElement).offset().top, e(t.view.frameElement).offset().left] : [0, 0]; switch (o) { case \"pointerdown\": case \"MSPointerDown\": case \"pointermove\": case \"MSPointerMove\": case \"pointerup\": case \"MSPointerUp\": return a ? [t.originalEvent.pageY - a[0] + n[0], t.originalEvent.pageX - a[1] + n[1], !1] : [t.originalEvent.pageY, t.originalEvent.pageX, !1]; case \"touchstart\": case \"touchmove\": case \"touchend\": var i = t.originalEvent.touches[0] || t.originalEvent.changedTouches[0], r = t.originalEvent.touches.length || t.originalEvent.changedTouches.length; return t.target.ownerDocument !== document ? [i.screenY, i.screenX, r > 1] : [i.pageY, i.pageX, r > 1]; default: return a ? [t.pageY - a[0] + n[0], t.pageX - a[1] + n[1], !1] : [t.pageY, t.pageX, !1] } }, I = function () { function t(e, t, a, n) { if (h[0].idleTimer = d.scrollInertia < 233 ? 250 : 0, o.attr(\"id\") === f[1]) var i = \"x\", s = (o[0].offsetLeft - t + n) * l.scrollRatio.x; else var i = \"y\", s = (o[0].offsetTop - e + a) * l.scrollRatio.y; G(r, s.toString(), { dir: i, drag: !0 }) } var o, n, i, r = e(this), l = r.data(a), d = l.opt, u = a + \"_\" + l.idx, f = [\"mCSB_\" + l.idx + \"_dragger_vertical\", \"mCSB_\" + l.idx + \"_dragger_horizontal\"], h = e(\"#mCSB_\" + l.idx + \"_container\"), m = e(\"#\" + f[0] + \",#\" + f[1]), p = d.advanced.releaseDraggableSelectors ? m.add(e(d.advanced.releaseDraggableSelectors)) : m, g = d.advanced.extraDraggableSelectors ? e(!A() || top.document).add(e(d.advanced.extraDraggableSelectors)) : e(!A() || top.document); m.bind(\"contextmenu.\" + u, function (e) { e.preventDefault() }).bind(\"mousedown.\" + u + \" touchstart.\" + u + \" pointerdown.\" + u + \" MSPointerDown.\" + u, function (t) { if (t.stopImmediatePropagation(), t.preventDefault(), ee(t)) { c = !0, s && (document.onselectstart = function () { return !1 }), L.call(h, !1), Q(r), o = e(this); var a = o.offset(), l = O(t)[0] - a.top, u = O(t)[1] - a.left, f = o.height() + a.top, m = o.width() + a.left; f > l && l > 0 && m > u && u > 0 && (n = l, i = u), C(o, \"active\", d.autoExpandScrollbar) } }).bind(\"touchmove.\" + u, function (e) { e.stopImmediatePropagation(), e.preventDefault(); var a = o.offset(), r = O(e)[0] - a.top, l = O(e)[1] - a.left; t(n, i, r, l) }), e(document).add(g).bind(\"mousemove.\" + u + \" pointermove.\" + u + \" MSPointerMove.\" + u, function (e) { if (o) { var a = o.offset(), r = O(e)[0] - a.top, l = O(e)[1] - a.left; if (n === r && i === l) return; t(n, i, r, l) } }).add(p).bind(\"mouseup.\" + u + \" touchend.\" + u + \" pointerup.\" + u + \" MSPointerUp.\" + u, function () { o && (C(o, \"active\", d.autoExpandScrollbar), o = null), c = !1, s && (document.onselectstart = null), L.call(h, !0) }) }, D = function () { function o(e) { if (!te(e) || c || O(e)[2]) return void (t = 0); t = 1, b = 0, C = 0, d = 1, y.removeClass(\"mCS_touch_action\"); var o = I.offset(); u = O(e)[0] - o.top, f = O(e)[1] - o.left, z = [O(e)[0], O(e)[1]] } function n(e) { if (te(e) && !c && !O(e)[2] && (T.documentTouchScroll || e.preventDefault(), e.stopImmediatePropagation(), (!C || b) && d)) { g = K(); var t = M.offset(), o = O(e)[0] - t.top, a = O(e)[1] - t.left, n = \"mcsLinearOut\"; if (E.push(o), W.push(a), z[2] = Math.abs(O(e)[0] - z[0]), z[3] = Math.abs(O(e)[1] - z[1]), B.overflowed[0]) var i = D[0].parent().height() - D[0].height(), r = u - o > 0 && o - u > -(i * B.scrollRatio.y) && (2 * z[3] < z[2] || \"yx\" === T.axis); if (B.overflowed[1]) var l = D[1].parent().width() - D[1].width(), h = f - a > 0 && a - f > -(l * B.scrollRatio.x) && (2 * z[2] < z[3] || \"yx\" === T.axis); r || h ? (U || e.preventDefault(), b = 1) : (C = 1, y.addClass(\"mCS_touch_action\")), U && e.preventDefault(), w = \"yx\" === T.axis ? [u - o, f - a] : \"x\" === T.axis ? [null, f - a] : [u - o, null], I[0].idleTimer = 250, B.overflowed[0] && s(w[0], R, n, \"y\", \"all\", !0), B.overflowed[1] && s(w[1], R, n, \"x\", L, !0) } } function i(e) { if (!te(e) || c || O(e)[2]) return void (t = 0); t = 1, e.stopImmediatePropagation(), Q(y), p = K(); var o = M.offset(); h = O(e)[0] - o.top, m = O(e)[1] - o.left, E = [], W = [] } function r(e) { if (te(e) && !c && !O(e)[2]) { d = 0, e.stopImmediatePropagation(), b = 0, C = 0, v = K(); var t = M.offset(), o = O(e)[0] - t.top, a = O(e)[1] - t.left; if (!(v - g > 30)) { _ = 1e3 / (v - p); var n = \"mcsEaseOut\", i = 2.5 > _, r = i ? [E[E.length - 2], W[W.length - 2]] : [0, 0]; x = i ? [o - r[0], a - r[1]] : [o - h, a - m]; var u = [Math.abs(x[0]), Math.abs(x[1])]; _ = i ? [Math.abs(x[0] / 4), Math.abs(x[1] / 4)] : [_, _]; var f = [Math.abs(I[0].offsetTop) - x[0] * l(u[0] / _[0], _[0]), Math.abs(I[0].offsetLeft) - x[1] * l(u[1] / _[1], _[1])]; w = \"yx\" === T.axis ? [f[0], f[1]] : \"x\" === T.axis ? [null, f[1]] : [f[0], null], S = [4 * u[0] + T.scrollInertia, 4 * u[1] + T.scrollInertia]; var y = parseInt(T.contentTouchScroll) || 0; w[0] = u[0] > y ? w[0] : 0, w[1] = u[1] > y ? w[1] : 0, B.overflowed[0] && s(w[0], S[0], n, \"y\", L, !1), B.overflowed[1] && s(w[1], S[1], n, \"x\", L, !1) } } } function l(e, t) { var o = [1.5 * t, 2 * t, t / 1.5, t / 2]; return e > 90 ? t > 4 ? o[0] : o[3] : e > 60 ? t > 3 ? o[3] : o[2] : e > 30 ? t > 8 ? o[1] : t > 6 ? o[0] : t > 4 ? t : o[2] : t > 8 ? t : o[3] } function s(e, t, o, a, n, i) { e && G(y, e.toString(), { dur: t, scrollEasing: o, dir: a, overwrite: n, drag: i }) } var d, u, f, h, m, p, g, v, x, _, w, S, b, C, y = e(this), B = y.data(a), T = B.opt, k = a + \"_\" + B.idx, M = e(\"#mCSB_\" + B.idx), I = e(\"#mCSB_\" + B.idx + \"_container\"), D = [e(\"#mCSB_\" + B.idx + \"_dragger_vertical\"), e(\"#mCSB_\" + B.idx + \"_dragger_horizontal\")], E = [], W = [], R = 0, L = \"yx\" === T.axis ? \"none\" : \"all\", z = [], P = I.find(\"iframe\"), H = [\"touchstart.\" + k + \" pointerdown.\" + k + \" MSPointerDown.\" + k, \"touchmove.\" + k + \" pointermove.\" + k + \" MSPointerMove.\" + k, \"touchend.\" + k + \" pointerup.\" + k + \" MSPointerUp.\" + k], U = void 0 !== document.body.style.touchAction && \"\" !== document.body.style.touchAction; I.bind(H[0], function (e) { o(e) }).bind(H[1], function (e) { n(e) }), M.bind(H[0], function (e) { i(e) }).bind(H[2], function (e) { r(e) }), P.length && P.each(function () { e(this).bind(\"load\", function () { A(this) && e(this.contentDocument || this.contentWindow.document).bind(H[0], function (e) { o(e), i(e) }).bind(H[1], function (e) { n(e) }).bind(H[2], function (e) { r(e) }) }) }) }, E = function () { function o() { return window.getSelection ? window.getSelection().toString() : document.selection && \"Control\" != document.selection.type ? document.selection.createRange().text : 0 } function n(e, t, o) { d.type = o && i ? \"stepped\" : \"stepless\", d.scrollAmount = 10, j(r, e, t, \"mcsLinearOut\", o ? 60 : null) } var i, r = e(this), l = r.data(a), s = l.opt, d = l.sequential, u = a + \"_\" + l.idx, f = e(\"#mCSB_\" + l.idx + \"_container\"), h = f.parent(); f.bind(\"mousedown.\" + u, function () { t || i || (i = 1, c = !0) }).add(document).bind(\"mousemove.\" + u, function (e) { if (!t && i && o()) { var a = f.offset(), r = O(e)[0] - a.top + f[0].offsetTop, c = O(e)[1] - a.left + f[0].offsetLeft; r > 0 && r < h.height() && c > 0 && c < h.width() ? d.step && n(\"off\", null, \"stepped\") : (\"x\" !== s.axis && l.overflowed[0] && (0 > r ? n(\"on\", 38) : r > h.height() && n(\"on\", 40)), \"y\" !== s.axis && l.overflowed[1] && (0 > c ? n(\"on\", 37) : c > h.width() && n(\"on\", 39))) } }).bind(\"mouseup.\" + u + \" dragend.\" + u, function () { t || (i && (i = 0, n(\"off\", null)), c = !1) }) }, W = function () { function t(t, a) { if (Q(o), !z(o, t.target)) { var r = \"auto\" !== i.mouseWheel.deltaFactor ? parseInt(i.mouseWheel.deltaFactor) : s && t.deltaFactor < 100 ? 100 : t.deltaFactor || 100, d = i.scrollInertia; if (\"x\" === i.axis || \"x\" === i.mouseWheel.axis) var u = \"x\", f = [Math.round(r * n.scrollRatio.x), parseInt(i.mouseWheel.scrollAmount)], h = \"auto\" !== i.mouseWheel.scrollAmount ? f[1] : f[0] >= l.width() ? .9 * l.width() : f[0], m = Math.abs(e(\"#mCSB_\" + n.idx + \"_container\")[0].offsetLeft), p = c[1][0].offsetLeft, g = c[1].parent().width() - c[1].width(), v = \"y\" === i.mouseWheel.axis ? t.deltaY || a : t.deltaX; else var u = \"y\", f = [Math.round(r * n.scrollRatio.y), parseInt(i.mouseWheel.scrollAmount)], h = \"auto\" !== i.mouseWheel.scrollAmount ? f[1] : f[0] >= l.height() ? .9 * l.height() : f[0], m = Math.abs(e(\"#mCSB_\" + n.idx + \"_container\")[0].offsetTop), p = c[0][0].offsetTop, g = c[0].parent().height() - c[0].height(), v = t.deltaY || a; \"y\" === u && !n.overflowed[0] || \"x\" === u && !n.overflowed[1] || ((i.mouseWheel.invert || t.webkitDirectionInvertedFromDevice) && (v = -v), i.mouseWheel.normalizeDelta && (v = 0 > v ? -1 : 1), (v > 0 && 0 !== p || 0 > v && p !== g || i.mouseWheel.preventDefault) && (t.stopImmediatePropagation(), t.preventDefault()), t.deltaFactor < 5 && !i.mouseWheel.normalizeDelta && (h = t.deltaFactor, d = 17), G(o, (m - v * h).toString(), { dir: u, dur: d })) } } if (e(this).data(a)) { var o = e(this), n = o.data(a), i = n.opt, r = a + \"_\" + n.idx, l = e(\"#mCSB_\" + n.idx), c = [e(\"#mCSB_\" + n.idx + \"_dragger_vertical\"), e(\"#mCSB_\" + n.idx + \"_dragger_horizontal\")], d = e(\"#mCSB_\" + n.idx + \"_container\").find(\"iframe\"); d.length && d.each(function () { e(this).bind(\"load\", function () { A(this) && e(this.contentDocument || this.contentWindow.document).bind(\"mousewheel.\" + r, function (e, o) { t(e, o) }) }) }), l.bind(\"mousewheel.\" + r, function (e, o) { t(e, o) }) } }, R = new Object, A = function (t) { var o = !1, a = !1, n = null; if (void 0 === t ? a = \"#empty\" : void 0 !== e(t).attr(\"id\") && (a = e(t).attr(\"id\")), a !== !1 && void 0 !== R[a]) return R[a]; if (t) { try { var i = t.contentDocument || t.contentWindow.document; n = i.body.innerHTML } catch (r) { } o = null !== n } else { try { var i = top.document; n = i.body.innerHTML } catch (r) { } o = null !== n } return a !== !1 && (R[a] = o), o }, L = function (e) { var t = this.find(\"iframe\"); if (t.length) { var o = e ? \"auto\" : \"none\"; t.css(\"pointer-events\", o) } }, z = function (t, o) { var n = o.nodeName.toLowerCase(), i = t.data(a).opt.mouseWheel.disableOver, r = [\"select\", \"textarea\"]; return e.inArray(n, i) > -1 && !(e.inArray(n, r) > -1 && !e(o).is(\":focus\")) }, P = function () { var t, o = e(this), n = o.data(a), i = a + \"_\" + n.idx, r = e(\"#mCSB_\" + n.idx + \"_container\"), l = r.parent(), s = e(\".mCSB_\" + n.idx + \"_scrollbar .\" + d[12]); s.bind(\"mousedown.\" + i + \" touchstart.\" + i + \" pointerdown.\" + i + \" MSPointerDown.\" + i, function (o) { c = !0, e(o.target).hasClass(\"mCSB_dragger\") || (t = 1) }).bind(\"touchend.\" + i + \" pointerup.\" + i + \" MSPointerUp.\" + i, function () { c = !1 }).bind(\"click.\" + i, function (a) { if (t && (t = 0, e(a.target).hasClass(d[12]) || e(a.target).hasClass(\"mCSB_draggerRail\"))) { Q(o); var i = e(this), s = i.find(\".mCSB_dragger\"); if (i.parent(\".mCSB_scrollTools_horizontal\").length > 0) { if (!n.overflowed[1]) return; var c = \"x\", u = a.pageX > s.offset().left ? -1 : 1, f = Math.abs(r[0].offsetLeft) - u * (.9 * l.width()) } else { if (!n.overflowed[0]) return; var c = \"y\", u = a.pageY > s.offset().top ? -1 : 1, f = Math.abs(r[0].offsetTop) - u * (.9 * l.height()) } G(o, f.toString(), { dir: c, scrollEasing: \"mcsEaseInOut\" }) } }) }, H = function () { var t = e(this), o = t.data(a), n = o.opt, i = a + \"_\" + o.idx, r = e(\"#mCSB_\" + o.idx + \"_container\"), l = r.parent(); r.bind(\"focusin.\" + i, function () { var o = e(document.activeElement), a = r.find(\".mCustomScrollBox\").length, i = 0; o.is(n.advanced.autoScrollOnFocus) && (Q(t), clearTimeout(t[0]._focusTimeout), t[0]._focusTimer = a ? (i + 17) * a : 0, t[0]._focusTimeout = setTimeout(function () { var e = [ae(o)[0], ae(o)[1]], a = [r[0].offsetTop, r[0].offsetLeft], s = [a[0] + e[0] >= 0 && a[0] + e[0] < l.height() - o.outerHeight(!1), a[1] + e[1] >= 0 && a[0] + e[1] < l.width() - o.outerWidth(!1)], c = \"yx\" !== n.axis || s[0] || s[1] ? \"all\" : \"none\"; \"x\" === n.axis || s[0] || G(t, e[0].toString(), { dir: \"y\", scrollEasing: \"mcsEaseInOut\", overwrite: c, dur: i }), \"y\" === n.axis || s[1] || G(t, e[1].toString(), { dir: \"x\", scrollEasing: \"mcsEaseInOut\", overwrite: c, dur: i }) }, t[0]._focusTimer)) }) }, U = function () { var t = e(this), o = t.data(a), n = a + \"_\" + o.idx, i = e(\"#mCSB_\" + o.idx + \"_container\").parent(); i.bind(\"scroll.\" + n, function () { 0 === i.scrollTop() && 0 === i.scrollLeft() || e(\".mCSB_\" + o.idx + \"_scrollbar\").css(\"visibility\", \"hidden\") }) }, F = function () { var t = e(this), o = t.data(a), n = o.opt, i = o.sequential, r = a + \"_\" + o.idx, l = \".mCSB_\" + o.idx + \"_scrollbar\", s = e(l + \">a\"); s.bind(\"contextmenu.\" + r, function (e) { e.preventDefault() }).bind(\"mousedown.\" + r + \" touchstart.\" + r + \" pointerdown.\" + r + \" MSPointerDown.\" + r + \" mouseup.\" + r + \" touchend.\" + r + \" pointerup.\" + r + \" MSPointerUp.\" + r + \" mouseout.\" + r + \" pointerout.\" + r + \" MSPointerOut.\" + r + \" click.\" + r, function (a) { function r(e, o) { i.scrollAmount = n.scrollButtons.scrollAmount, j(t, e, o) } if (a.preventDefault(), ee(a)) { var l = e(this).attr(\"class\"); switch (i.type = n.scrollButtons.scrollType, a.type) { case \"mousedown\": case \"touchstart\": case \"pointerdown\": case \"MSPointerDown\": if (\"stepped\" === i.type) return; c = !0, o.tweenRunning = !1, r(\"on\", l); break; case \"mouseup\": case \"touchend\": case \"pointerup\": case \"MSPointerUp\": case \"mouseout\": case \"pointerout\": case \"MSPointerOut\": if (\"stepped\" === i.type) return; c = !1, i.dir && r(\"off\", l); break; case \"click\": if (\"stepped\" !== i.type || o.tweenRunning) return; r(\"on\", l) } } }) }, q = function () { function t(t) { function a(e, t) { r.type = i.keyboard.scrollType, r.scrollAmount = i.keyboard.scrollAmount, \"stepped\" === r.type && n.tweenRunning || j(o, e, t) } switch (t.type) { case \"blur\": n.tweenRunning && r.dir && a(\"off\", null); break; case \"keydown\": case \"keyup\": var l = t.keyCode ? t.keyCode : t.which, s = \"on\"; if (\"x\" !== i.axis && (38 === l || 40 === l) || \"y\" !== i.axis && (37 === l || 39 === l)) { if ((38 === l || 40 === l) && !n.overflowed[0] || (37 === l || 39 === l) && !n.overflowed[1]) return; \"keyup\" === t.type && (s = \"off\"), e(document.activeElement).is(u) || (t.preventDefault(), t.stopImmediatePropagation(), a(s, l)) } else if (33 === l || 34 === l) { if ((n.overflowed[0] || n.overflowed[1]) && (t.preventDefault(), t.stopImmediatePropagation()), \"keyup\" === t.type) { Q(o); var f = 34 === l ? -1 : 1; if (\"x\" === i.axis || \"yx\" === i.axis && n.overflowed[1] && !n.overflowed[0]) var h = \"x\", m = Math.abs(c[0].offsetLeft) - f * (.9 * d.width()); else var h = \"y\", m = Math.abs(c[0].offsetTop) - f * (.9 * d.height()); G(o, m.toString(), { dir: h, scrollEasing: \"mcsEaseInOut\" }) } } else if ((35 === l || 36 === l) && !e(document.activeElement).is(u) && ((n.overflowed[0] || n.overflowed[1]) && (t.preventDefault(), t.stopImmediatePropagation()), \"keyup\" === t.type)) { if (\"x\" === i.axis || \"yx\" === i.axis && n.overflowed[1] && !n.overflowed[0]) var h = \"x\", m = 35 === l ? Math.abs(d.width() - c.outerWidth(!1)) : 0; else var h = \"y\", m = 35 === l ? Math.abs(d.height() - c.outerHeight(!1)) : 0; G(o, m.toString(), { dir: h, scrollEasing: \"mcsEaseInOut\" }) } } } var o = e(this), n = o.data(a), i = n.opt, r = n.sequential, l = a + \"_\" + n.idx, s = e(\"#mCSB_\" + n.idx), c = e(\"#mCSB_\" + n.idx + \"_container\"), d = c.parent(), u = \"input,textarea,select,datalist,keygen,[contenteditable='true']\", f = c.find(\"iframe\"), h = [\"blur.\" + l + \" keydown.\" + l + \" keyup.\" + l]; f.length && f.each(function () { e(this).bind(\"load\", function () { A(this) && e(this.contentDocument || this.contentWindow.document).bind(h[0], function (e) { t(e) }) }) }), s.attr(\"tabindex\", \"0\").bind(h[0], function (e) { t(e) }) }, j = function (t, o, n, i, r) { function l(e) { u.snapAmount && (f.scrollAmount = u.snapAmount instanceof Array ? \"x\" === f.dir[0] ? u.snapAmount[1] : u.snapAmount[0] : u.snapAmount); var o = \"stepped\" !== f.type, a = r ? r : e ? o ? p / 1.5 : g : 1e3 / 60, n = e ? o ? 7.5 : 40 : 2.5, s = [Math.abs(h[0].offsetTop), Math.abs(h[0].offsetLeft)], d = [c.scrollRatio.y > 10 ? 10 : c.scrollRatio.y, c.scrollRatio.x > 10 ? 10 : c.scrollRatio.x], m = \"x\" === f.dir[0] ? s[1] + f.dir[1] * (d[1] * n) : s[0] + f.dir[1] * (d[0] * n), v = \"x\" === f.dir[0] ? s[1] + f.dir[1] * parseInt(f.scrollAmount) : s[0] + f.dir[1] * parseInt(f.scrollAmount), x = \"auto\" !== f.scrollAmount ? v : m, _ = i ? i : e ? o ? \"mcsLinearOut\" : \"mcsEaseInOut\" : \"mcsLinear\", w = !!e; return e && 17 > a && (x = \"x\" === f.dir[0] ? s[1] : s[0]), G(t, x.toString(), { dir: f.dir[0], scrollEasing: _, dur: a, onComplete: w }), e ? void (f.dir = !1) : (clearTimeout(f.step), void (f.step = setTimeout(function () { l() }, a))) } function s() { clearTimeout(f.step), $(f, \"step\"), Q(t) } var c = t.data(a), u = c.opt, f = c.sequential, h = e(\"#mCSB_\" + c.idx + \"_container\"), m = \"stepped\" === f.type, p = u.scrollInertia < 26 ? 26 : u.scrollInertia, g = u.scrollInertia < 1 ? 17 : u.scrollInertia; switch (o) { case \"on\": if (f.dir = [n === d[16] || n === d[15] || 39 === n || 37 === n ? \"x\" : \"y\", n === d[13] || n === d[15] || 38 === n || 37 === n ? -1 : 1], Q(t), oe(n) && \"stepped\" === f.type) return; l(m); break; case \"off\": s(), (m || c.tweenRunning && f.dir) && l(!0) } }, Y = function (t) { var o = e(this).data(a).opt, n = []; return \"function\" == typeof t && (t = t()), t instanceof Array ? n = t.length > 1 ? [t[0], t[1]] : \"x\" === o.axis ? [null, t[0]] : [t[0], null] : (n[0] = t.y ? t.y : t.x || \"x\" === o.axis ? null : t, n[1] = t.x ? t.x : t.y || \"y\" === o.axis ? null : t), \"function\" == typeof n[0] && (n[0] = n[0]()), \"function\" == typeof n[1] && (n[1] = n[1]()), n }, X = function (t, o) { if (null != t && \"undefined\" != typeof t) { var n = e(this), i = n.data(a), r = i.opt, l = e(\"#mCSB_\" + i.idx + \"_container\"), s = l.parent(), c = typeof t; o || (o = \"x\" === r.axis ? \"x\" : \"y\"); var d = \"x\" === o ? l.outerWidth(!1) - s.width() : l.outerHeight(!1) - s.height(), f = \"x\" === o ? l[0].offsetLeft : l[0].offsetTop, h = \"x\" === o ? \"left\" : \"top\"; switch (c) { case \"function\": return t(); case \"object\": var m = t.jquery ? t : e(t); if (!m.length) return; return \"x\" === o ? ae(m)[1] : ae(m)[0]; case \"string\": case \"number\": if (oe(t)) return Math.abs(t); if (-1 !== t.indexOf(\"%\")) return Math.abs(d * parseInt(t) / 100); if (-1 !== t.indexOf(\"-=\")) return Math.abs(f - parseInt(t.split(\"-=\")[1])); if (-1 !== t.indexOf(\"+=\")) { var p = f + parseInt(t.split(\"+=\")[1]); return p >= 0 ? 0 : Math.abs(p) } if (-1 !== t.indexOf(\"px\") && oe(t.split(\"px\")[0])) return Math.abs(t.split(\"px\")[0]); if (\"top\" === t || \"left\" === t) return 0; if (\"bottom\" === t) return Math.abs(s.height() - l.outerHeight(!1)); if (\"right\" === t) return Math.abs(s.width() - l.outerWidth(!1)); if (\"first\" === t || \"last\" === t) { var m = l.find(\":\" + t); return \"x\" === o ? ae(m)[1] : ae(m)[0] } return e(t).length ? \"x\" === o ? ae(e(t))[1] : ae(e(t))[0] : (l.css(h, t), void u.update.call(null, n[0])) } } }, N = function (t) {\n                    function o() { return clearTimeout(f[0].autoUpdate), 0 === l.parents(\"html\").length ? void (l = null) : void (f[0].autoUpdate = setTimeout(function () { return c.advanced.updateOnSelectorChange && (s.poll.change.n = i(), s.poll.change.n !== s.poll.change.o) ? (s.poll.change.o = s.poll.change.n, void r(3)) : c.advanced.updateOnContentResize && (s.poll.size.n = l[0].scrollHeight + l[0].scrollWidth + f[0].offsetHeight + l[0].offsetHeight + l[0].offsetWidth, s.poll.size.n !== s.poll.size.o) ? (s.poll.size.o = s.poll.size.n, void r(1)) : !c.advanced.updateOnImageLoad || \"auto\" === c.advanced.updateOnImageLoad && \"y\" === c.axis || (s.poll.img.n = f.find(\"img\").length, s.poll.img.n === s.poll.img.o) ? void ((c.advanced.updateOnSelectorChange || c.advanced.updateOnContentResize || c.advanced.updateOnImageLoad) && o()) : (s.poll.img.o = s.poll.img.n, void f.find(\"img\").each(function () { n(this) })) }, c.advanced.autoUpdateTimeout)) } function n(t) {\n                        function o(e, t) {\n                            return function () {\n                                return t.apply(e, arguments)\n                            }\n                        } function a() { this.onload = null, e(t).addClass(d[2]), r(2) } if (e(t).hasClass(d[2])) return void r(); var n = new Image; n.onload = o(n, a), n.src = t.src\n                    } function i() { c.advanced.updateOnSelectorChange === !0 && (c.advanced.updateOnSelectorChange = \"*\"); var e = 0, t = f.find(c.advanced.updateOnSelectorChange); return c.advanced.updateOnSelectorChange && t.length > 0 && t.each(function () { e += this.offsetHeight + this.offsetWidth }), e } function r(e) { clearTimeout(f[0].autoUpdate), u.update.call(null, l[0], e) } var l = e(this), s = l.data(a), c = s.opt, f = e(\"#mCSB_\" + s.idx + \"_container\"); return t ? (clearTimeout(f[0].autoUpdate), void $(f[0], \"autoUpdate\")) : void o()\n                }, V = function (e, t, o) { return Math.round(e / t) * t - o }, Q = function (t) { var o = t.data(a), n = e(\"#mCSB_\" + o.idx + \"_container,#mCSB_\" + o.idx + \"_container_wrapper,#mCSB_\" + o.idx + \"_dragger_vertical,#mCSB_\" + o.idx + \"_dragger_horizontal\"); n.each(function () { Z.call(this) }) }, G = function (t, o, n) { function i(e) { return s && c.callbacks[e] && \"function\" == typeof c.callbacks[e] } function r() { return [c.callbacks.alwaysTriggerOffsets || w >= S[0] + y, c.callbacks.alwaysTriggerOffsets || -B >= w] } function l() { var e = [h[0].offsetTop, h[0].offsetLeft], o = [x[0].offsetTop, x[0].offsetLeft], a = [h.outerHeight(!1), h.outerWidth(!1)], i = [f.height(), f.width()]; t[0].mcs = { content: h, top: e[0], left: e[1], draggerTop: o[0], draggerLeft: o[1], topPct: Math.round(100 * Math.abs(e[0]) / (Math.abs(a[0]) - i[0])), leftPct: Math.round(100 * Math.abs(e[1]) / (Math.abs(a[1]) - i[1])), direction: n.dir } } var s = t.data(a), c = s.opt, d = { trigger: \"internal\", dir: \"y\", scrollEasing: \"mcsEaseOut\", drag: !1, dur: c.scrollInertia, overwrite: \"all\", callbacks: !0, onStart: !0, onUpdate: !0, onComplete: !0 }, n = e.extend(d, n), u = [n.dur, n.drag ? 0 : n.dur], f = e(\"#mCSB_\" + s.idx), h = e(\"#mCSB_\" + s.idx + \"_container\"), m = h.parent(), p = c.callbacks.onTotalScrollOffset ? Y.call(t, c.callbacks.onTotalScrollOffset) : [0, 0], g = c.callbacks.onTotalScrollBackOffset ? Y.call(t, c.callbacks.onTotalScrollBackOffset) : [0, 0]; if (s.trigger = n.trigger, 0 === m.scrollTop() && 0 === m.scrollLeft() || (e(\".mCSB_\" + s.idx + \"_scrollbar\").css(\"visibility\", \"visible\"), m.scrollTop(0).scrollLeft(0)), \"_resetY\" !== o || s.contentReset.y || (i(\"onOverflowYNone\") && c.callbacks.onOverflowYNone.call(t[0]), s.contentReset.y = 1), \"_resetX\" !== o || s.contentReset.x || (i(\"onOverflowXNone\") && c.callbacks.onOverflowXNone.call(t[0]), s.contentReset.x = 1), \"_resetY\" !== o && \"_resetX\" !== o) { if (!s.contentReset.y && t[0].mcs || !s.overflowed[0] || (i(\"onOverflowY\") && c.callbacks.onOverflowY.call(t[0]), s.contentReset.x = null), !s.contentReset.x && t[0].mcs || !s.overflowed[1] || (i(\"onOverflowX\") && c.callbacks.onOverflowX.call(t[0]), s.contentReset.x = null), c.snapAmount) { var v = c.snapAmount instanceof Array ? \"x\" === n.dir ? c.snapAmount[1] : c.snapAmount[0] : c.snapAmount; o = V(o, v, c.snapOffset) } switch (n.dir) { case \"x\": var x = e(\"#mCSB_\" + s.idx + \"_dragger_horizontal\"), _ = \"left\", w = h[0].offsetLeft, S = [f.width() - h.outerWidth(!1), x.parent().width() - x.width()], b = [o, 0 === o ? 0 : o / s.scrollRatio.x], y = p[1], B = g[1], T = y > 0 ? y / s.scrollRatio.x : 0, k = B > 0 ? B / s.scrollRatio.x : 0; break; case \"y\": var x = e(\"#mCSB_\" + s.idx + \"_dragger_vertical\"), _ = \"top\", w = h[0].offsetTop, S = [f.height() - h.outerHeight(!1), x.parent().height() - x.height()], b = [o, 0 === o ? 0 : o / s.scrollRatio.y], y = p[0], B = g[0], T = y > 0 ? y / s.scrollRatio.y : 0, k = B > 0 ? B / s.scrollRatio.y : 0 }b[1] < 0 || 0 === b[0] && 0 === b[1] ? b = [0, 0] : b[1] >= S[1] ? b = [S[0], S[1]] : b[0] = -b[0], t[0].mcs || (l(), i(\"onInit\") && c.callbacks.onInit.call(t[0])), clearTimeout(h[0].onCompleteTimeout), J(x[0], _, Math.round(b[1]), u[1], n.scrollEasing), !s.tweenRunning && (0 === w && b[0] >= 0 || w === S[0] && b[0] <= S[0]) || J(h[0], _, Math.round(b[0]), u[0], n.scrollEasing, n.overwrite, { onStart: function () { n.callbacks && n.onStart && !s.tweenRunning && (i(\"onScrollStart\") && (l(), c.callbacks.onScrollStart.call(t[0])), s.tweenRunning = !0, C(x), s.cbOffsets = r()) }, onUpdate: function () { n.callbacks && n.onUpdate && i(\"whileScrolling\") && (l(), c.callbacks.whileScrolling.call(t[0])) }, onComplete: function () { if (n.callbacks && n.onComplete) { \"yx\" === c.axis && clearTimeout(h[0].onCompleteTimeout); var e = h[0].idleTimer || 0; h[0].onCompleteTimeout = setTimeout(function () { i(\"onScroll\") && (l(), c.callbacks.onScroll.call(t[0])), i(\"onTotalScroll\") && b[1] >= S[1] - T && s.cbOffsets[0] && (l(), c.callbacks.onTotalScroll.call(t[0])), i(\"onTotalScrollBack\") && b[1] <= k && s.cbOffsets[1] && (l(), c.callbacks.onTotalScrollBack.call(t[0])), s.tweenRunning = !1, h[0].idleTimer = 0, C(x, \"hide\") }, e) } } }) } }, J = function (e, t, o, a, n, i, r) { function l() { S.stop || (x || m.call(), x = K() - v, s(), x >= S.time && (S.time = x > S.time ? x + f - (x - S.time) : x + f - 1, S.time < x + 1 && (S.time = x + 1)), S.time < a ? S.id = h(l) : g.call()) } function s() { a > 0 ? (S.currVal = u(S.time, _, b, a, n), w[t] = Math.round(S.currVal) + \"px\") : w[t] = o + \"px\", p.call() } function c() { f = 1e3 / 60, S.time = x + f, h = window.requestAnimationFrame ? window.requestAnimationFrame : function (e) { return s(), setTimeout(e, .01) }, S.id = h(l) } function d() { null != S.id && (window.requestAnimationFrame ? window.cancelAnimationFrame(S.id) : clearTimeout(S.id), S.id = null) } function u(e, t, o, a, n) { switch (n) { case \"linear\": case \"mcsLinear\": return o * e / a + t; case \"mcsLinearOut\": return e /= a, e--, o * Math.sqrt(1 - e * e) + t; case \"easeInOutSmooth\": return e /= a / 2, 1 > e ? o / 2 * e * e + t : (e--, -o / 2 * (e * (e - 2) - 1) + t); case \"easeInOutStrong\": return e /= a / 2, 1 > e ? o / 2 * Math.pow(2, 10 * (e - 1)) + t : (e--, o / 2 * (-Math.pow(2, -10 * e) + 2) + t); case \"easeInOut\": case \"mcsEaseInOut\": return e /= a / 2, 1 > e ? o / 2 * e * e * e + t : (e -= 2, o / 2 * (e * e * e + 2) + t); case \"easeOutSmooth\": return e /= a, e--, -o * (e * e * e * e - 1) + t; case \"easeOutStrong\": return o * (-Math.pow(2, -10 * e / a) + 1) + t; case \"easeOut\": case \"mcsEaseOut\": default: var i = (e /= a) * e, r = i * e; return t + o * (.499999999999997 * r * i + -2.5 * i * i + 5.5 * r + -6.5 * i + 4 * e) } } e._mTween || (e._mTween = { top: {}, left: {} }); var f, h, r = r || {}, m = r.onStart || function () { }, p = r.onUpdate || function () { }, g = r.onComplete || function () { }, v = K(), x = 0, _ = e.offsetTop, w = e.style, S = e._mTween[t]; \"left\" === t && (_ = e.offsetLeft); var b = o - _; S.stop = 0, \"none\" !== i && d(), c() }, K = function () { return window.performance && window.performance.now ? window.performance.now() : window.performance && window.performance.webkitNow ? window.performance.webkitNow() : Date.now ? Date.now() : (new Date).getTime() }, Z = function () { var e = this; e._mTween || (e._mTween = { top: {}, left: {} }); for (var t = [\"top\", \"left\"], o = 0; o < t.length; o++) { var a = t[o]; e._mTween[a].id && (window.requestAnimationFrame ? window.cancelAnimationFrame(e._mTween[a].id) : clearTimeout(e._mTween[a].id), e._mTween[a].id = null, e._mTween[a].stop = 1) } }, $ = function (e, t) { try { delete e[t] } catch (o) { e[t] = null } }, ee = function (e) { return !(e.which && 1 !== e.which) }, te = function (e) { var t = e.originalEvent.pointerType; return !(t && \"touch\" !== t && 2 !== t) }, oe = function (e) { return !isNaN(parseFloat(e)) && isFinite(e) }, ae = function (e) { var t = e.parents(\".mCSB_container\"); return [e.offset().top - t.offset().top, e.offset().left - t.offset().left] }, ne = function () { function e() { var e = [\"webkit\", \"moz\", \"ms\", \"o\"]; if (\"hidden\" in document) return \"hidden\"; for (var t = 0; t < e.length; t++)if (e[t] + \"Hidden\" in document) return e[t] + \"Hidden\"; return null } var t = e(); return t ? document[t] : !1 }; e.fn[o] = function (t) { return u[t] ? u[t].apply(this, Array.prototype.slice.call(arguments, 1)) : \"object\" != typeof t && t ? void e.error(\"Method \" + t + \" does not exist\") : u.init.apply(this, arguments) }, e[o] = function (t) { return u[t] ? u[t].apply(this, Array.prototype.slice.call(arguments, 1)) : \"object\" != typeof t && t ? void e.error(\"Method \" + t + \" does not exist\") : u.init.apply(this, arguments) }, e[o].defaults = i, window[o] = !0, e(window).bind(\"load\", function () { e(n)[o](), e.extend(e.expr[\":\"], { mcsInView: e.expr[\":\"].mcsInView || function (t) { var o, a, n = e(t), i = n.parents(\".mCSB_container\"); if (i.length) return o = i.parent(), a = [i[0].offsetTop, i[0].offsetLeft], a[0] + ae(n)[0] >= 0 && a[0] + ae(n)[0] < o.height() - n.outerHeight(!1) && a[1] + ae(n)[1] >= 0 && a[1] + ae(n)[1] < o.width() - n.outerWidth(!1) }, mcsInSight: e.expr[\":\"].mcsInSight || function (t, o, a) { var n, i, r, l, s = e(t), c = s.parents(\".mCSB_container\"), d = \"exact\" === a[3] ? [[1, 0], [1, 0]] : [[.9, .1], [.6, .4]]; if (c.length) return n = [s.outerHeight(!1), s.outerWidth(!1)], r = [c[0].offsetTop + ae(s)[0], c[0].offsetLeft + ae(s)[1]], i = [c.parent()[0].offsetHeight, c.parent()[0].offsetWidth], l = [n[0] < i[0] ? d[0] : d[1], n[1] < i[1] ? d[0] : d[1]], r[0] - i[0] * l[0][0] < 0 && r[0] + n[0] - i[0] * l[0][1] >= 0 && r[1] - i[1] * l[1][0] < 0 && r[1] + n[1] - i[1] * l[1][1] >= 0 }, mcsOverflow: e.expr[\":\"].mcsOverflow || function (t) { var o = e(t).data(a); if (o) return o.overflowed[0] || o.overflowed[1] } }) })\n            })\n        });\n\n        function __GetUrlValue(name) {\n            var reg = new RegExp(\"(^|&)\" + name + \"=([^&]*)(&|$)\", \"i\");\n            var r = window.location.search.substr(1).match(reg);\n            if (r != null) return decodeURIComponent(r[2]); return null;\n        };\n\n        function __GetCookie(cookieName) {\n            var theCookie = \"\" + document.cookie;\n            var ind = theCookie.indexOf(cookieName + \"=\");\n            if (ind == -1 || cookieName == \"\")\n                return \"\";\n            var ind1 = theCookie.indexOf(';', ind);\n            if (ind1 == -1)\n                ind1 = theCookie.length;\n            return unescape(theCookie.substring(ind + cookieName.length + 1, ind1));\n        }\n\n        function __SetCookie(name, value, days) {\n            var Days = days || 365;\n            var exp = new Date(); //new Date('December 31, 9998');\n            exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000);\n            document.cookie = name + '=' + escape(value) + ';expires=' + exp.toGMTString() + '; path=/; domain=.bilibili.com';\n        }\n\n        function ChatGetSettings(key) {\n            if (typeof (localStorage) != 'undefined' && localStorage && localStorage.getItem) {\n                return localStorage.getItem(key);\n            } else {\n                return __GetCookie(key);\n            }\n        }\n\n        function ChatSaveSettings(key, val) {\n            if (typeof (localStorage) != 'undefined' && localStorage && localStorage.setItem) {\n                try {\n                    return localStorage.setItem(key, val);\n                } catch (e) {\n                    console.warn(e);\n                }\n            } else {\n                return __SetCookie(key, val);\n            }\n        }\n\n        var allow = true;\n        if (window.top != window.self && window.REFERRER_LIST) {\n            try {\n                var h = window.document.referrer.match(/^http(s)?:\\/\\/(.*?)\\//);\n                if (h && h[2] && !(new RegExp(window.REFERRER_LIST.join('|').replace(/\\./g, '\\\\.').replace(/\\*/g, '\\.\\*'))).test(h[2])) {\n                    allow = false;\n                } else if (!window.document.referrer && window.navigator.userAgent.indexOf('MicroMessenger') === -1 && window.navigator.userAgent.indexOf('IqiyiApp') === -1) {\n                    allow = false;\n                }\n            } catch (e) {\n\n            }\n        }\n\n        //from page.arc.js\n        function flashChecker() {\n            var hasFlash = false;\n            var flashVersion = 0;\n            if (navigator.plugins && navigator.plugins.length > 0) {\n                var swf = navigator.plugins[\"Shockwave Flash\"];\n                if (swf) {\n                    hasFlash = true;\n                    var words = swf.description.split(\" \");\n                    for (var i = 0; i < words.length; ++i) {\n                        if (isNaN(parseInt(words[i]))) continue;\n                        flashVersion = parseInt(words[i]);\n                    }\n                }\n            }\n            return { hasFlash: hasFlash, flashVersion: flashVersion };\n        };\n\n        if (__GetUrlValue('crossDomain')) {\n            document.domain = 'bilibili.com';\n        }\n\n        window.browser = { version: function () { var b = navigator.userAgent; return { trident: /Trident/i.test(b), presto: /Presto/i.test(b), webKit: /AppleWebKit/i.test(b), gecko: /Gecko/i.test(b) && !/KHTML/i.test(b), mobile: /AppleWebKit.*Mobile.*/i.test(b), ios: /\\(i[^;]+;( U;)? CPU.+Mac OS X/i.test(b), android: /Android/i.test(b) || /Linux/i.test(b), windowsphone: /Windows Phone/i.test(b), iPhone: /iPhone/i.test(b), iPad: /iPad/i.test(b), MicroMessenger: /MicroMessenger/i.test(b), webApp: !/Safari/i.test(b) } }(), language: (navigator.browserLanguage || navigator.language).toLowerCase() };\n\n        function videoLoader() {\n            this.config = {\n                'player': $(\"#bofqi\"),\n                'aid': __GetUrlValue('aid'),\n                'page': __GetUrlValue('page') || 1,\n                'roomid': __GetUrlValue('roomid'),\n                'autoplay': __GetUrlValue('autoplay'),\n                'sendbar': __GetUrlValue('sendbar'),\n                'as_wide': 1, // 默认以宽屏模式载入\n                'cid': __GetUrlValue('cid'),\n                'bnj': __GetUrlValue('bnj'),\n                \"player_type\": __GetUrlValue('player_type'),\n                \"season_type\": __GetUrlValue('season_type')\n            };\n            this.flashAddEvents = [];\n            this.flashRemoveEvents = [];\n            this.hasFlash = flashChecker().hasFlash;\n            this.gray_html5 = true;\n\n            //不支持IE10及以下浏览器 不支持Win7 IE11\n            if (/msie [\\w.]+/.exec(navigator.userAgent.toLowerCase()) || /edge/i.exec(navigator.userAgent) || ((/Trident/i).test(navigator.userAgent) && (/Windows NT 6/.test(navigator.userAgent)))) {\n                this.gray_html5 = false;\n            }\n\n            if (((/linux/i).test(navigator.userAgent.toLowerCase()) || (/Mac OS X[\\s\\_\\-\\/](\\d+[\\.\\-\\_]\\d+[\\.\\-\\_]?\\d*)/i).test(navigator.userAgent)) || !flashChecker().hasFlash) {\n                if (ChatGetSettings('defaulth5') == null) {\n                    ChatSaveSettings(\"defaulth5\", 1);\n                }\n            }\n\n            if (!this.config['cid']) {\n                this.getCid();\n            } else {\n                this.init();\n            }\n        }\n        videoLoader.prototype.getCid = function () {\n            var self = this;\n            $.ajax({\n                url: '//api.bilibili.com/view?type=json&appkey=8e9fc618fbd41e28&id=' + this.config['aid'] + '&page=' + this.config['page'],\n                type: 'get',\n                data: {\n                    'type': 'jsonp'\n                },\n                dataType: 'jsonp',\n                success: function (data) {\n                    if (data) {\n                        self.config['cid'] = data.cid;\n                    }\n                    self.init();\n                },\n                error: function () {\n                    self.init();\n                }\n            });\n        };\n\n        videoLoader.prototype.init = function () {\n            if (!(ChatGetSettings('defaulth5') == 1 && this.gray_html5)) {\n                if (this.config.aid) {\n                    this.loadFlashPlayer();\n                } else if (this.config.roomid) {\n                    this.loadFlashLivePlayer();\n                }\n            } else {\n                var self = this;\n\n                if (this.config.roomid) {\n                    $('<link rel=\"stylesheet\" type=\"text/css\" href=\"//static.hdslb.com/css/simple.v2.min.css\" />').appendTo('body');\n                    $.getScript(\"//static.hdslb.com/js/simple.v2.min.js\", function () {\n                        self.config.player.addClass('html5');\n                        if (self.config.sendbar) {\n                            self.config.player.after('<div id=\"dm_send_bar\"><input type=\"text\" id=\"dm_send_input\" maxlength=\"200\" disabled placeholder=\"输入弹幕╮( ̄▽ ̄)╭\" value=\"\" /><button id=\"dm_send_btn\" class=\"disabled\">发送</button></div>');\n                            self.config.player.hide().height($(window).height() - $(\"#dm_send_bar\").height()).show();\n                            $(window).resize(function () {\n                                self.config.player.hide().height($(window).height() - $(\"#dm_send_bar\").height()).show();\n                            });\n                        }\n                        self.h5player = new BiliH5Player();\n                        self.loadHtml5LivePlayer();\n                    });\n                } else {\n                    self.loadHtml5Player();\n                }\n            }\n        };\n\n        videoLoader.prototype.loadHtml5Player = function () {\n            var self = this;\n            this.videoType = 'html5';\n            ChatSaveSettings(\"defaulth5\", 1);\n            if (!window.bilibiliPlayer) {\n                $('<link rel=\"stylesheet\" type=\"text/css\" href=\"//static.hdslb.com/plugins/mCustomScrollbar/jquery.mCustomScrollbar.min.css\" />').appendTo('body');\n\n                $.ajax({\n                    url: '//static.hdslb.com/player/js/bilibiliPlayer.min.js',\n                    cache: true,\n                    type: 'get',\n                    dataType: 'script',\n                    success: function () {\n                        $('#bofqi').html('<div class=\"player\"><div id=\"bilibiliPlayer\"></div></div><iframe style=\"display: none\"></iframe><div id=\"player_placeholder\"></div>');\n                        window.player = new bilibiliPlayer({\n                            aid: self.config.aid,\n                            cid: self.config.cid,\n                            p: self.config.page,\n                            autoplay: (self.config.autoplay == true),\n                            as_wide: self.config.as_wide,\n                            bnj: self.config.bnj,\n                            player_type: self.config.player_type,\n                            season_type: self.config.season_type\n                        });\n                        //compatible\n                        self.gray_html5_compatible();\n                    }\n                });\n            } else {\n                $('#bofqi').html('<div class=\"player\"><div id=\"bilibiliPlayer\"></div></div><iframe style=\"display: none\"></iframe><div id=\"player_placeholder\"></div>');\n                window.player = new bilibiliPlayer({\n                    aid: self.config.aid,\n                    cid: self.config.cid,\n                    p: self.config.page,\n                    autoplay: (self.config.autoplay == true),\n                    as_wide: self.config.as_wide,\n                    bnj: self.config.bnj\n                });\n                //compatible\n                self.gray_html5_compatible();\n            }\n        }\n\n        videoLoader.prototype.gray_html5_compatible = function () {\n            var eventMaps = {\n                'jwplayerMediaBuffer': 'video_media_buffer',\n                'jwplayerMediaBufferFull': 'video_media_buffer_full',\n                'jwplayerMediaComplete': 'video_media_ended',\n                'jwplayerMediaError': 'video_media_error',\n                'jwplayerMediaLoaded': 'video_media_loaded',\n                'jwplayerMediaMute': 'video_media_mute',\n                'jwplayerMediaSeek': 'video_media_seek',\n                'jwplayerMediaTime': 'video_media_time',\n                'jwplayerMediaVolume': 'video_media_volume'\n            };\n            var apiMaps = {\n                'mukio_reloadAccess': 'reloadAccess',\n                // 'jwAddEventListener': 'addEventListener',\n                // 'jwRemoveEventListener': 'removeEventListener',\n                'jwPlay': 'play',\n                'jwPause': 'pause',\n                'jwStop': 'stop',\n                'jwSeek': 'seek',\n                'jwPlaylistPrev': 'prev',\n                'jwPlaylistNext': 'next',\n                'jwGetBuffer': 'getBufferRate',\n                'jwGetDuration': 'getDuration',\n                'jwGetFullscreen': 'isFullScreen',\n                'jwGetWidth': 'getWidth',\n                'jwGetHeight': 'getHeight',\n                'jwGetMute': 'isMute',\n                'jwSetMute': 'setMute',\n                'jwGetPlaylist': 'getPlaylist',\n                'jwGetPlaylistIndex': 'getPlaylistIndex',\n                'jwGetPosition': 'getCurrentTime',\n                'jwGetState': 'getState',\n                'jwGetVersion': 'getVersion',\n                'jwGetVolume': 'volume',\n                'jwSetVolume': 'volume'\n            };\n            var c_head, c_element;\n            try {\n                c_head = $(window.parent.document.body);\n                c_element = $(window.parent.document.body).find('#player_placeholder');\n            } catch (e) {\n                c_head = $('#bofqi');\n                c_element = $('#bofqi').find('#player_placeholder');\n            }\n            if (c_element.length === 0) {\n                c_element = $('<div id=\"player_placeholder\" style=\"display: none;\"></div>').appendTo(c_head);\n            }\n            c_element = c_element[0];\n\n            for (var i in apiMaps) {\n                (function (flashName, html5Name) {\n                    c_element[flashName] = function () {\n                        if (window.player && typeof window.player[html5Name] === 'function') {\n                            return window.player[html5Name].apply(window.player, arguments);\n                        }\n                    }\n                })(i, apiMaps[i]);\n            }\n\n            c_element.jwAddEventListener = function (type, callback) {\n                try {\n                    if (typeof callback !== 'function') {\n                        callback = eval('(' + callback + ')');\n                    }\n                } catch (e) {\n                    callback = function () { };\n                }\n                if (eventMaps[type]) {\n                    window.player && window.player.addEventListener && window.player.addEventListener(eventMaps[type], callback);\n                }\n            };\n\n            c_element.jwRemoveEventListener = function (type) {\n                if (eventMaps[type]) {\n                    window.player && window.player.removeEventListener && window.player.removeEventListener(eventMaps[type]);\n                }\n            }\n\n            try {\n                window.parent.player = window.player;\n            } catch (e) { }\n\n        };\n\n        videoLoader.prototype.gray_flash_compatible = function () {\n            var self = this;\n            var eventMaps = {\n                'jwplayerMediaBuffer': 'video_media_buffer',\n                'jwplayerMediaBufferFull': 'video_media_buffer_full',\n                'jwplayerMediaComplete': 'video_media_ended',\n                'jwplayerMediaError': 'video_media_error',\n                'jwplayerMediaLoaded': 'video_media_loaded',\n                'jwplayerMediaMute': 'video_media_mute',\n                'jwplayerMediaSeek': 'video_media_seek',\n                'jwplayerMediaTime': 'video_media_time',\n                'jwplayerMediaVolume': 'video_media_volume'\n            };\n            var apiMaps = {\n                'mukio_reloadAccess': 'reloadAccess',\n                // 'jwAddEventListener': 'addEventListener',\n                // 'jwRemoveEventListener': 'removeEventListener',\n                'jwPlay': 'play',\n                'jwPause': 'pause',\n                'jwStop': 'stop',\n                'jwSeek': 'seek',\n                'jwPlaylistPrev': 'prev',\n                'jwPlaylistNext': 'next',\n                'jwGetBuffer': 'getBufferRate',\n                'jwGetDuration': 'getDuration',\n                'jwGetFullscreen': 'isFullScreen',\n                'jwGetWidth': 'getWidth',\n                'jwGetHeight': 'getHeight',\n                'jwGetMute': 'isMute',\n                'jwSetMute': 'setMute',\n                'jwGetPlaylist': 'getPlaylist',\n                'jwGetPlaylistIndex': 'getPlaylistIndex',\n                'jwGetPosition': 'getCurrentTime',\n                'jwGetState': 'getState',\n                'jwGetVersion': 'getVersion',\n                'jwGetVolume': 'volume',\n                'jwSetVolume': 'volume'\n            };\n            var c_head, c_element;\n            try {\n                c_head = $(window.parent.document.body);\n                c_element = $(window.parent.document.body).find('#player_placeholder');\n            } catch (e) {\n                return false;\n            }\n            if (c_element.length === 0) {\n                c_element = $('<div id=\"player_placeholder\" style=\"display: none;\"></div>').appendTo(c_head);\n            }\n            c_element = c_element[0];\n\n            for (var i in apiMaps) {\n                (function (flashName, html5Name) {\n                    c_element[flashName] = function () {\n                        try {\n                            $('#player_placeholder')[0][flashName].apply(this, arguments);\n                        } catch (e) {\n                            console.log(e);\n                        }\n                    };\n                })(i, apiMaps[i]);\n            }\n\n            c_element.jwAddEventListener = function () {\n                try {\n                    $('#player_placeholder')[0]['jwAddEventListener'].apply(this, arguments);\n                } catch (e) {\n                    console.log(e);\n                }\n            }\n            c_element.jwRemoveEventListener = function () {\n                try {\n                    $('#player_placeholder')[0]['jwRemoveEventListener'].apply(this, arguments);\n                } catch (e) {\n                    console.log(e);\n                }\n            }\n\n            // 统一的播放器对外方法\n            window.player = {};\n\n            var eventMaps = {\n                'video_media_buffer': 'jwplayerMediaBuffer',\n                'video_media_buffer_full': 'jwplayerMediaBufferFull',\n                'video_media_ended': 'jwplayerMediaComplete',\n                'video_media_error': 'jwplayerMediaError',\n                'video_media_loaded': 'jwplayerMediaLoaded',\n                'video_media_mute': 'jwplayerMediaMute',\n                'video_media_seek': 'jwplayerMediaSeek',\n                'video_media_time': 'jwplayerMediaTime',\n                'video_media_volume': 'jwplayerMediaVolume'\n            };\n            var apiMaps = {\n                'reloadAccess': 'mukio_reloadAccess',\n                'play': 'jwPlay',\n                'pause': 'jwPause',\n                'stop': 'jwStop',\n                'seek': 'jwSeek',\n                'prev': 'jwPlaylistPrev',\n                'next': 'jwPlaylistNext',\n                'getBufferRate': 'jwGetBuffer',\n                'getDuration': 'jwGetDuration',\n                'isFullScreen': 'jwGetFullscreen',\n                'getWidth': 'jwGetWidth',\n                'getHeight': 'jwGetHeight',\n                'isMute': 'jwGetMute',\n                'setMute': 'jwSetMute',\n                'getPlaylist': 'jwGetPlaylist',\n                'getPlaylistIndex': 'jwGetPlaylistIndex',\n                'getCurrentTime': 'jwGetPosition',\n                'getState': 'jwGetState',\n                'getVersion': 'jwGetVersion',\n                'volume': 'jwGetVolume|jwSetVolume' // special\n            };\n\n            for (var i in apiMaps) {\n                (function (html5Name, flashName) {\n                    window.player[html5Name] = function () {\n                        var flashBox = document.getElementById('player_placeholder');\n                        if (flashBox) {\n                            if (typeof flashBox[flashName] === 'function') {\n                                return flashBox[flashName].apply(flashBox, arguments);\n                            } else if (html5Name === 'volume' && typeof flashBox['volume'] === 'function') {\n                                if (arguments.length === 0) {\n                                    return flashBox['jwGetVolume'].apply(flashBox, arguments);\n                                } else {\n                                    return flashBox['jwSetVolume'].apply(flashBox, arguments);\n                                }\n                            }\n                        }\n                    }\n                })(i, apiMaps[i]);\n            }\n\n            window.player['addEventListener'] = function (type, callback) {\n                try {\n                    if (typeof callback !== 'function') {\n                        callback = eval('(' + callback + ')');\n                    }\n                } catch (e) {\n                    callback = function () { };\n                }\n\n                if (eventMaps[type]) {\n                    self.flashAddEvents.push([type, callback]);\n                }\n            };\n\n            window.player['removeEventListener'] = function (type) {\n                if (eventMaps[type]) {\n                    for (var i = self.flashAddEvents.length - 1; i > 0; i--) {\n                        if (self.flashAddEvents[i][0] == type) {\n                            self.flashAddEvents.splice(i, 1);\n                        }\n                    }\n                }\n            }\n\n            try {\n                window.parent.player = window.player;\n            } catch (e) { }\n        };\n\n        videoLoader.prototype.loadFlashTimer = function () {\n            var eventMaps = {\n                'jwplayerMediaBuffer': 'video_media_buffer',\n                'jwplayerMediaBufferFull': 'video_media_buffer_full',\n                'jwplayerMediaComplete': 'video_media_ended',\n                'jwplayerMediaError': 'video_media_error',\n                'jwplayerMediaLoaded': 'video_media_loaded',\n                'jwplayerMediaMute': 'video_media_mute',\n                'jwplayerMediaSeek': 'video_media_seek',\n                'jwplayerMediaTime': 'video_media_time',\n                'jwplayerMediaVolume': 'video_media_volume'\n            };\n            var stime = +new Date();\n            var self = this;\n            var ftimer = setInterval(function () {\n                if (+new Date() - stime > 10000) {\n                    clearTimeout(ftimer);\n                }\n                var flashBox = document.getElementById('player_placeholder'),\n                    func;\n                if (flashBox && flashBox.jwAddEventListener) {\n                    flashBox.jwAddEventListener('jwplayerMediaBuffer', 'function(){loader.callFunction(\"video_media_buffer\")}');\n                    flashBox.jwAddEventListener('jwplayerMediaBufferFull', 'function(){loader.callFunction(\"video_media_buffer_full\")}');\n                    flashBox.jwAddEventListener('jwplayerMediaComplete', 'function(){loader.callFunction(\"video_media_ended\")}');\n                    flashBox.jwAddEventListener('jwplayerMediaError', 'function(){loader.callFunction(\"video_media_error\")}');\n                    flashBox.jwAddEventListener('jwplayerMediaLoaded', 'function(){loader.callFunction(\"video_media_loaded\")}');\n                    flashBox.jwAddEventListener('jwplayerMediaMute', 'function(){loader.callFunction(\"video_media_mute\")}');\n                    flashBox.jwAddEventListener('jwplayerMediaSeek', 'function(){loader.callFunction(\"video_media_seek\")}');\n                    flashBox.jwAddEventListener('jwplayerMediaTime', 'function(){loader.callFunction(\"video_media_time\")}');\n                    flashBox.jwAddEventListener('jwplayerMediaVolume', 'function(){loader.callFunction(\"video_media_volume\")}');\n                    clearTimeout(ftimer);\n                }\n            }, 1);\n        };\n\n        videoLoader.prototype.callFunction = function (type) {\n            var eventMaps = {\n                'video_media_buffer': 'jwplayerMediaBuffer',\n                'video_media_buffer_full': 'jwplayerMediaBufferFull',\n                'video_media_ended': 'jwplayerMediaComplete',\n                'video_media_error': 'jwplayerMediaError',\n                'video_media_loaded': 'jwplayerMediaLoaded',\n                'video_media_mute': 'jwplayerMediaMute',\n                'video_media_seek': 'jwplayerMediaSeek',\n                'video_media_time': 'jwplayerMediaTime',\n                'video_media_volume': 'jwplayerMediaVolume'\n            };\n            if (eventMaps[type]) {\n                for (var i = 0; i < this.flashAddEvents.length; i++) {\n                    this.flashAddEvents[i] && this.flashAddEvents[i][0] == type && this.flashAddEvents[i][1]();\n                }\n            }\n        };\n\n        videoLoader.prototype.loadFlashPlayer = function () {\n            var self = this;\n            this.flashAddEvents = [];\n            this.videoType = 'flash';\n            ChatSaveSettings(\"defaulth5\", 0);\n            self.config.player.html('<object type=\"application/x-shockwave-flash\" class=\"player\" data=\"//static.hdslb.com/play.swf\" id=\"player_placeholder\" style=\"visibility: visible;\">'\n                + '<param name=\"allowfullscreeninteractive\" value=\"true\"><param name=\"allowfullscreen\" value=\"true\"><param name=\"quality\" value=\"high\">'\n                + '<param name=\"allowscriptaccess\" value=\"always\"><param name=\"wmode\" value=\"' + (__GetUrlValue('wmode') || 'direct') + '\">'\n                + '<param name=\"flashvars\" value=\"cid=' + self.config.cid + '&aid=' + self.config.aid + '&as_wide=' + (self.config.as_wide ? 1 : 0) + (self.config.autoplay ? '&autoplay=1' : '') + '\">'\n                + '<param name=\"movie\" value=\"//static.hdslb.com/play.swf\"/>'\n                + '</object>');\n            self.gray_flash_compatible();\n            self.loadFlashTimer();\n        };\n\n        videoLoader.prototype.loadFlashLivePlayer = function () {\n            this.config.player.html('<object type=\"application/x-shockwave-flash\" data=\"//static.hdslb.com/live-static/swf/LivePlayerEx_1.swf\" width=\"100%\" height=\"100%\" id=\"player_object\" style=\"visibility: visible;\">'\n                + '<param name=\"allowfullscreeninteractive\" value=\"true\"><param name=\"allowfullscreen\" value=\"true\"><param name=\"quality\" value=\"high\">'\n                + '<param name=\"allowscriptaccess\" value=\"always\"><param name=\"wmode\" value=\"transparent\"><param name=\"autostart\" value=\"0\">'\n                + '<param name=\"flashvars\" value=\"onready=playerOnReady&autostart=0&room_id=' + this.config.roomid + '&cid=' + this.config.roomid + '&cover=//i2.hdslb.com/u_user/activities/201507chinajoy/images/cover_reverse.png&state=LIVE\">'\n                + '</object>');\n        }\n\n        videoLoader.prototype.loadHtml5LivePlayer = function () {\n            var self = this;\n            var source = {\n                'image': \"//i2.hdslb.com/u_user/activities/201507chinajoy/images/cover_reverse.png\"\n            };\n            $.ajax({\n                url: \"//live.bilibili.com/api/h5playurl?roomid=\" + self.config.roomid,\n                dataType: \"jsonp\",\n                success: function (result) {\n                    if (result && result.durl && result.durl[0]) {\n                        source.comment = (location.protocol === 'https:' ? \"wss:\" : \"ws:\") + \"//livecmt.bilibili.com:88/\" + self.config.roomid;\n                        source.video_url = result.durl[0].url;\n                    }\n                    self.h5player.create({\n                        \"live\": true,\n                        \"autoplay\": self.config.autoplay,\n                        \"on_state_change\": function (a, b) {\n                            self.loadHtml5Callback(a, b);\n                        },\n                        \"get_from_local\": true,\n                        \"comment\": source.comment,\n                        \"image\": source.image,\n                        \"video_url\": source.video_url\n                    });\n                },\n                error: function () { }\n            });\n        };\n\n        videoLoader.prototype.loadHtml5Callback = function (now_status, origin_status) {\n            var self = this;\n            if (now_status == 1 && origin_status == 0 && self.config.sendbar) {\n                self.config.sendbar = false;\n                $('#bofqi').after('<div id=\"dm_send_bar\"><input type=\"text\" id=\"dm_send_input\" maxlength=\"200\" placeholder=\"点击此处开始吐槽!\" value=\"\" /><button id=\"dm_send_btn\">发送</button></div>');\n                $(\"#bofqi\").height($(window).height() - $(\"#dm_send_bar\").height());\n                $(window).resize(function () {\n                    $(\"#bofqi\").height($(window).height() - $(\"#dm_send_bar\").height());\n                });\n                $(\"#dm_send_bar\").addClass('float').appendTo('.display');\n                var send_btn = $(\"#dm_send_btn\");\n                var send_input = $(\"#dm_send_input\");\n                send_btn.removeClass(\"disabled\");\n                send_input.removeAttr(\"disabled\");\n\n                send_btn.bind('click', function () {\n                    if (send_btn.hasClass(\"disabled\") || $.trim(send_input.val()) == \"\") {\n                        return false;\n                    } else {\n                        send_input.attr(\"disabled\");\n                        send_btn.addClass(\"disabled\");\n                        var sendTimeout = setTimeout(function () {\n                            send_input.val(\"\");\n                            send_btn.removeClass(\"disabled\");\n                            send_input.removeAttr(\"disabled\");\n                        }, 3000);\n                    }\n                    splayer.sendComment({\n                        \"msg\": $.trim(send_input.val()),\n                        \"color\": 0xffffff\n                    }, function (data) {\n                        clearTimeout(sendTimeout);\n                        send_input.val(\"\");\n                        send_input.removeAttr(\"disabled\");\n                        send_btn.removeClass(\"disabled\");\n                    }, function (data) {\n                        clearTimeout(sendTimeout);\n                        send_input.val(\"\");\n                        send_input.removeAttr(\"disabled\");\n                        send_btn.removeClass(\"disabled\");\n                    }\n                    );\n                });\n            }\n        };\n\n        videoLoader.prototype.loadExtraMenuConfig = function (type) {\n            var v = null;\n            var exconfig = [];\n            if (type === 'flash' || type === 'flash_gray') {\n                if (this.gray_html5) {\n                    exconfig.push({ label: \"HTML5播放器\", id: \"change_h5\" });\n                    exconfig.push({ label: \"Flash播放器\", id: \"change_flash\", active: true });\n                }\n            } else {\n                exconfig.push({ label: \"HTML5播放器\", id: \"change_h5\", active: true });\n                exconfig.push({ label: \"Flash播放器\", id: \"change_flash\" });\n            }\n            v = '20161115';\n            return { 'ver': v, 'menuItems': exconfig };\n        };\n\n        videoLoader.prototype.clickMenu = function (id) {\n            // console.debug('click event: ' + id);\n            var self = this;\n            setTimeout(function () {\n                if (id === 'change_h5') {\n                    self.search_new_cid(function () {\n                        self.loadHtml5Player();\n                    });\n                } else if (id === 'change_flash') {\n                    self.search_new_cid(function () {\n                        window.player && window.player.destroy && window.player.destroy();\n                        self.loadFlashPlayer();\n                    });\n                }\n            }, 0);\n\n            return true;\n        };\n\n        videoLoader.prototype.search_new_cid = function (callback) {\n            if (typeof callback === 'function') {\n                callback();\n            }\n            // var self = this;\n            // if(this.videoType == 'html5') {\n            //     this.config['page'] = player.getPlaylistIndex() + 1;\n            // }\n            // $.ajax({\n            //     url: '//www.bilibili.com/widget/getPageList?aid=' + this.config['aid'],\n            //     cache: true,\n            //     type: 'get',\n            //     xhrFields: {\n            //         withCredentials: true\n            //     },\n            //     dataType: 'json',\n            //     success: function(data) {\n            //         if(data) {\n            //             for(var i in data) {\n            //                 if(data[i]['page'] == self.config['page']) {\n            //                     self.config['cid'] = data[i]['cid'];\n            //                 }\n            //             }\n            //         }\n            //         callback();\n            //     },\n            //     error: function() {\n            //         callback();\n            //     }\n            // });\n        };\n\n        if (allow) {\n            var loader = new videoLoader();\n        }\n\n        window.callNextPart = function () {\n            try {\n                loader.config['page']++;\n                if (typeof window.parent.callNextPart === 'function') {\n                    window.parent.callNextPart.apply(this, arguments);\n                }\n            } catch (e) {\n            }\n        };\n\n        window.PlayerSetOnline = function () {\n            try {\n                if (typeof window.parent.PlayerSetOnline === 'function') {\n                    window.parent.PlayerSetOnline.apply(this, arguments);\n                }\n            } catch (e) {\n            }\n        };\n\n        window.showHideVideo = function () {\n            try {\n                if (typeof window.parent.showHideVideo === 'function') {\n                    window.parent.showHideVideo.apply(this, arguments);\n                }\n            } catch (e) {\n            }\n        };\n\n        window.heimu = function () {\n            try {\n                if (typeof window.parent.heimu === 'function') {\n                    window.parent.heimu.apply(this, arguments);\n                }\n            } catch (e) {\n            }\n        };\n\n        window.UserStatus = {\n            quickLogin: function () {\n                try {\n                    if (window.parent.UserStatus && typeof window.parent.UserStatus.quickLogin === 'function') {\n                        window.parent.UserStatus.quickLogin.apply(this, arguments);\n                    } else if (window.parent.biliQuickLogin) {\n                        window.parent.biliQuickLogin.apply(this, arguments);\n                    }\n                } catch (e) {\n                }\n            }\n        };\n\n        window.player_fullwin = function () {\n            try {\n                if (typeof window.parent.player_fullwin === 'function') {\n                    window.parent.player_fullwin.apply(this, arguments);\n                }\n            } catch (e) {\n            }\n        };\n\n        window.callAppointPart = function () {\n            try {\n                if (typeof window.parent.callAppointPart === 'function') {\n                    window.parent.callAppointPart.apply(this, arguments);\n                }\n            } catch (e) {\n            }\n        };\n\n        window.playerCallSendCoin = function () {\n            try {\n                if (typeof window.parent.playerCallSendCoin === 'function') {\n                    window.parent.playerCallSendCoin.apply(this, arguments);\n                }\n            } catch (e) {\n            }\n        };\n\n        try {\n            window.GrayManager = {\n                loadExtraMenuConfig: function (type) {\n                    return loader.loadExtraMenuConfig(type);\n                },\n                clickMenu: function (id) {\n                    return loader.clickMenu(id);\n                }\n            };\n            window.parent.GrayManager = window.GrayManager;\n            $(window.parent.document).find('iframe#bofqi_embed').addClass('bilibiliHtml5Player');\n            var h = $(window.parent.document).find('head');\n            if (!h.find('style.bilibiliHtml5PlayerClass').length) {\n                $('<style class=\"bilibiliHtml5PlayerClass\">.player-fullscreen-fix {position: fixed;top: 0;left: 0;margin: 0;padding: 0;width: 100%;height: 100%;}'\n                    + '.player-fullscreen-fix iframe#bofqi_embed {position: fixed!important;border-radius: 0;z-index: 100000!important;left: 0;top: 0;width: 100%!important;height: 100%!important;}</style>').appendTo(h);\n            }\n        } catch (e) {\n\n        }\n\n        $(window).on('unload', function () {\n            try {\n                player && player.destroy();\n            } catch (e) {\n\n            }\n        });\n    </script>\n</body>\n\n</html>";
    modules["playlist-detail.html"] = "<!DOCTYPE html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\n<head>\n    <title>哔哩哔哩 (゜-゜)つロ 干杯~-bilibili</title>\n    <meta charset=\"utf-8\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n    <meta name=\"renderer\" content=\"webkit\" />\n    <meta name=\"description\" content=\"bilibili是国内知名的视频弹幕网站,这里有最及时的动漫新番,最棒的ACG氛围,最有创意的Up主。大家可以在这里找到许多欢乐。\" />\n    <link rel=\"stylesheet\" href=\"//static.hdslb.com/phoenix/dist/css/comment.min.css\" type=\"text/css\" />\n    <meta name=\"keywords\" content=\"B站,弹幕,字幕,AMV,MAD,MTV,ANIME,动漫,动漫音乐,游戏,游戏解说,ACG,galgame,动画,番组,新番,初音,洛天依,vocaloid\" />\n    <script type=\"text/javascript\" src=\"//static.hdslb.com/js/jquery.min.js\"></script>\n    <link rel=\"preload\"\n        href=\"//s1.hdslb.com/bfs/static/jinkela/playlist-detail/manifest.dc2f20722afb93b15bbf7a30436f70ff31fb0a05.js\"\n        as=\"script\" />\n    <link rel=\"preload\"\n        href=\"//s1.hdslb.com/bfs/static/jinkela/playlist-detail/vendor.dc2f20722afb93b15bbf7a30436f70ff31fb0a05.js\"\n        as=\"script\" />\n    <link rel=\"preload\"\n        href=\"//s1.hdslb.com/bfs/static/jinkela/playlist-detail/playlist_detail.dc2f20722afb93b15bbf7a30436f70ff31fb0a05.js\"\n        as=\"script\" />\n    <link rel=\"preload\"\n        href=\"//s1.hdslb.com/bfs/static/jinkela/playlist-detail/css/playlist_detail.1.dc2f20722afb93b15bbf7a30436f70ff31fb0a05.css\"\n        as=\"style\" />\n    <link rel=\"stylesheet\"\n        href=\"//s1.hdslb.com/bfs/static/jinkela/playlist-detail/css/playlist_detail.1.dc2f20722afb93b15bbf7a30436f70ff31fb0a05.css\" />\n</head>\n\n<body>\n    <div id=\"playlist-detail-app\"></div>\n    <div id=\"app\" data-server-rendered=\"true\" class=\"pl-app\"></div>\n    <script src=\"//s1.hdslb.com/bfs/static/jinkela/playlist-detail/manifest.dc2f20722afb93b15bbf7a30436f70ff31fb0a05.js\"\n        defer=\"defer\"></script>\n    <script src=\"//s1.hdslb.com/bfs/static/jinkela/playlist-detail/vendor.dc2f20722afb93b15bbf7a30436f70ff31fb0a05.js\"\n        defer=\"defer\"></script>\n    <script\n        src=\"//s1.hdslb.com/bfs/static/jinkela/playlist-detail/playlist_detail.dc2f20722afb93b15bbf7a30436f70ff31fb0a05.js\"\n        defer=\"defer\"></script>\n    <div class=\"footer bili-footer report-wrap-module\"></div>\n    <script type=\"text/javascript\" charset=\"utf-8\" src=\"//static.hdslb.com/common/js/footer.js\"></script>\n    <script type=\"text/javascript\" src=\"//static.hdslb.com/phoenix/dist/js/comment.min.js\"></script>\n</body>\n\n</html>";
    modules["playlist.html"] = "<!DOCTYPE html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\n<head>\n  <title>哔哩哔哩 (゜-゜)つロ 干杯~-bilibili</title>\n  <meta charset=\"utf-8\" />\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n  <meta name=\"renderer\" content=\"webkit\" />\n  <meta name=\"description\" content=\"bilibili是国内知名的视频弹幕网站,这里有最及时的动漫新番,最棒的ACG氛围,最有创意的Up主。大家可以在这里找到许多欢乐。\" />\n  <meta name=\"keywords\" content=\"B站,弹幕,字幕,AMV,MAD,MTV,ANIME,动漫,动漫音乐,游戏,游戏解说,ACG,galgame,动画,番组,新番,初音,洛天依,vocaloid\" />\n  <link rel=\"stylesheet\" href=\"//static.hdslb.com/phoenix/dist/css/comment.min.css\" type=\"text/css\" />\n  <meta charset=\"utf-8\" />\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n  <meta name=\"renderer\" content=\"webkit\" />\n  <meta name=\"description\" content=\"bilibili是国内知名的视频弹幕网站,这里有最及时的动漫新番,最棒的ACG氛围,最有创意的Up主。大家可以在这里找到许多欢乐。\" />\n  <meta name=\"keywords\" content=\"B站,弹幕,字幕,AMV,MAD,MTV,ANIME,动漫,动漫音乐,游戏,游戏解说,ACG,galgame,动画,番组,新番,初音,洛天依,vocaloid\" />\n  <link\n    href=\"//s1.hdslb.com/bfs/static/jinkela/playlist-video/css/playlist_video.0.87292febba67b03f65d05c15d03e325d9db4f56a.css\"\n    rel=\"stylesheet\" />\n  <script type=\"text/javascript\" src=\"//s1.hdslb.com/bfs/static/jinkela/long/js/jquery/jquery1.7.2.min.js\"></script>\n</head>\n\n<body>\n  <div id=\"playlist-video-app\"></div>\n  <div class=\"footer bili-footer report-wrap-module\"></div>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/js/jquery.qrcode.min.js\"></script>\n  <script type=\"text/javascript\" charset=\"utf-8\" src=\"//static.hdslb.com/common/js/footer.js\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/js/swfobject.js\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/js/video.min.js\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/mstation/js/upload/moxie.js\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/mstation/js/upload/plupload.js\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/phoenix/dist/js/comment.min.js\"></script>\n  <script type=\"text/javascript\"\n    src=\"//s1.hdslb.com/bfs/static/jinkela/playlist-video/1.playlist_video.87292febba67b03f65d05c15d03e325d9db4f56a.js\"></script>\n  <script type=\"text/javascript\"\n    src=\"//s1.hdslb.com/bfs/static/jinkela/playlist-video/playlist_video.87292febba67b03f65d05c15d03e325d9db4f56a.js\"></script>\n</body>\n\n</html>";
    modules["ranking.html"] = "<!DOCTYPE html>\n<html lang=\"zh-Hans\" xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"zh-Hans\">\n\n<head>\n  <title>热门视频排行榜 - 哔哩哔哩 (゜-゜)つロ 干杯~-bilibili</title>\n  <meta charset=\"utf-8\" />\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n  <meta name=\"renderer\" content=\"webkit\" />\n  <meta name=\"description\" content=\"bilibili是国内知名的视频弹幕网站,这里有最及时的动漫新番,最棒的ACG氛围,最有创意的Up主。大家可以在这里找到许多欢乐。\" />\n  <meta name=\"keywords\" content=\"B站,弹幕,字幕,AMV,MAD,MTV,ANIME,动漫,动漫音乐,游戏,游戏解说,ACG,galgame,动画,番组,新番,初音,洛天依,vocaloid\" />\n  <link rel=\"stylesheet\"\n    href=\"//s1.hdslb.com/bfs/static/jinkela/rank/css/rank.0.ba58f8684a87651e0e1c576df8f918bfa10c1a90.css\" />\n  <script type=\"text/javascript\" src=\"//s1.hdslb.com/bfs/static/jinkela/long/js/jquery/jquery1.7.2.min.js\"></script>\n</head>\n\n<body>\n  <div class=\"z-top-container has-menu\"></div>\n  <div id=\"rank-app\"></div>\n  <script type=\"text/javascript\" src=\"//s1.hdslb.com/bfs/seed/jinkela/header/header.js\" defer=\"defer\"></script>\n  <script type=\"text/javascript\" src=\"//s1.hdslb.com/bfs/cm/st/bundle.js\" crossorigin=\"\"></script>\n  <div id=\"app\" data-server-rendered=\"true\"></div>\n  <script src=\"//s1.hdslb.com/bfs/static/jinkela/rank/1.rank.ba58f8684a87651e0e1c576df8f918bfa10c1a90.js\"\n    defer=\"defer\"></script>\n  <script src=\"//s1.hdslb.com/bfs/static/jinkela/rank/rank.ba58f8684a87651e0e1c576df8f918bfa10c1a90.js\"\n    defer=\"defer\"></script>\n  <div class=\"footer bili-footer report-wrap-module\"></div>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/common/js/footer.js\" defer=\"defer\"></script>\n</body>\n\n</html>";
    modules["read.html"] = "<!DOCTYPE html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\n<head itemprop=\"Article\" itemscope=\"itemscope\" itemtype=\"http://schema.org/Article\">\n    <meta charset=\"UTF-8\" />\n    <meta data-n-head=\"true\" name=\"viewport\" content=\"width=device-width,initial-scale=1,user-scalable=0\" />\n    <meta name=\"theme-color\" content=\"#de698c\" />\n    <meta http=\"Cache-Control\" content=\"no-transform\" />\n    <meta name=\"format-detection\" content=\"telephone=no\" />\n    <meta name=\"applicable-device\" content=\"pc\" />\n    <link rel=\"apple-touch-icon-precomposed\" href=\"//static.hdslb.com/mobile/img/512.png\" />\n    <link rel=\"icon\" type=\"image/vnd.microsoft.icon\" href=\"//www.bilibili.com/favicon.ico\" />\n    <link rel=\"apple-touch-icon\" href=\"//www.bilibili.com/favicon.ico\" />\n    <meta name=\"renderer\" content=\"webkit\" />\n    <link data-n-head=\"true\" rel=\"icon\" type=\"image/x-icon\" href=\"//www.bilibili.com/favicon.ico\" />\n    <link data-n-head=\"true\" rel=\"apple-touch-icon-precomposed\" type=\"image/x-icon\"\n        href=\"//static.hdslb.com/mobile/img/512.png\" />\n    <title>哔哩哔哩专栏</title>\n    <link href=\"//s1.hdslb.com/bfs/static/jinkela/article/pcDetail.e5d43b1ea4f5a12408d8cd222049b34cfacd107c.css\"\n        rel=\"stylesheet\" />\n</head>\n\n<body>\n    <div class=\"z-top-container report-wrap-module\"></div>\n    <div class=\"page-container\"></div>\n    <div class=\"footer bili-footer report-wrap-module\" id=\"home_footer\"></div>\n    <script src=\"//static.hdslb.com/public/intersection-observer.js\"></script>\n    <script src=\"//static.hdslb.com/public/timing.min.js\"></script>\n    <script>\n        window.performanceLog.setSource('article');\n        window.reportMsgObj = {};\n    </script>\n    <script src=\"//static.hdslb.com/js/jquery-3.3.1.min.js\"></script>\n    <script type=\"text/javascript\" charset=\"utf-8\" src=\"//s1.hdslb.com/bfs/seed/jinkela/header/header.js\"></script>\n    <script type=\"text/javascript\" charset=\"utf-8\" src=\"//static.hdslb.com/common/js/footer.js\"></script>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"//static.hdslb.com/phoenix/dist/css/comment.min.css\" />\n    <script type=\"text/javascript\" src=\"//static.hdslb.com/phoenix/dist/js/comment.min.js\"></script>\n    <script src=\"//s1.hdslb.com/bfs/static/biliapp/biliapp.js\"></script>\n    <script type=\"text/javascript\"\n        src=\"//s1.hdslb.com/bfs/static/jinkela/article/manifest.e5d43b1ea4f5a12408d8cd222049b34cfacd107c.js\"></script>\n    <script type=\"text/javascript\"\n        src=\"//s1.hdslb.com/bfs/static/jinkela/article/vendor.e5d43b1ea4f5a12408d8cd222049b34cfacd107c.js\"></script>\n    <script type=\"text/javascript\"\n        src=\"//s1.hdslb.com/bfs/static/jinkela/article/pcDetail.e5d43b1ea4f5a12408d8cd222049b34cfacd107c.js\"></script>\n</body>\n\n</html>";
    modules["watchlater.html"] = "<!DOCTYPE html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\n<head>\n  <meta charset=\"utf-8\" />\n  <title>哔哩哔哩 (゜-゜)つロ 干杯~-bilibili</title>\n  <meta name=\"description\" content=\"bilibili是国内知名的视频弹幕网站,这里有最及时的动漫新番,最棒的ACG氛围,最有创意的Up主。大家可以在这里找到许多欢乐。\" />\n  <meta name=\"keywords\" content=\"B站,弹幕,字幕,AMV,MAD,MTV,ANIME,动漫,动漫音乐,游戏,游戏解说,ACG,galgame,动画,番组,新番,初音,洛天依,vocaloid\" />\n  <meta name=\"renderer\" content=\"webkit\" />\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n  <link rel=\"shortcut icon\" href=\"//static.hdslb.com/images/favicon.ico\" />\n  <link rel=\"search\" type=\"application/opensearchdescription+xml\" href=\"//static.hdslb.com/opensearch.xml\"\n    title=\"哔哩哔哩\" />\n  <link rel=\"stylesheet\" href=\"//static.hdslb.com/phoenix/dist/css/comment.min.css\" type=\"text/css\" />\n  <link rel=\"stylesheet\" href=\"//static.hdslb.com/elec_2/dist/css/later_elec.css\" type=\"text/css\" />\n  <link rel=\"stylesheet\" href=\"//static.hdslb.com/tag/css/tag-index2.0.css\" type=\"text/css\" />\n  <link href=\"//s1.hdslb.com/bfs/static/phoenix/viewlater/static/css/main.d9641d2f4dc42228ea8c2650e1b98b0b.css\"\n    rel=\"stylesheet\" />\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/js/jquery.min.js\"></script>\n</head>\n\n<body>\n  <div class=\"z-top-container has-menu\"></div>\n  <div id=\"viewlater-app\">\n    <app></app>\n  </div>\n  <div class=\"footer bili-footer\"></div>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/js/jquery.qrcode.min.js\"></script>\n  <script type=\"text/javascript\" src=\"//s1.hdslb.com/bfs/seed/jinkela/header/header.js\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/common/js/footer.js\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/js/swfobject.js\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/js/video.min.js\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/account/bili_quick_login.js\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/phoenix/dist/js/comment.min.js\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/mstation/js/upload/moxie.js\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/mstation/js/upload/plupload.js\"></script>\n  <script type=\"text/javascript\" src=\"//static.hdslb.com/elec_2/dist/js/later_elec.js\"></script>\n  <script type=\"text/javascript\"\n    src=\"//s1.hdslb.com/bfs/static/phoenix/viewlater/static/js/main.2111469a1bbc20e2e885.js\"></script>\n</body>\n\n</html>";
    modules["apply.json"] = {    "timeFormat": "format.js",    "sizeFormat": "format.js",    "unitFormat": "format.js",    "bubbleSort": "format.js",    "randomArray": "format.js",    "objUrl": "format.js",    "urlObj": "format.js",    "addCss": "extend.js",    "addElement": "extend.js",    "localModule": "manage.js",    "readFile": "manage.js",    "getCookies": "extend.js",    "loginExit": "extend.js",    "jsonCheck": "extend.js",    "restorePlayerSetting": "extend.js",    "biliQuickLogin": "extend.js",    "getTotalTop": "extend.js",    "abv": "abv.js",    "jsonphook": "Node.js",    "removeJsonphook": "jsonp.js",    "scriptIntercept": "Node.js",    "xhrhook": "open.js",    "removeXhrhook": "open.js",    "getSegDanmaku": "danmaku.js",    "specialEffects": "danmaku.js",    "sortDmById": "danmaku.js",    "toXml": "danmaku.js",    "getHistoryDanmaku": "danmaku.js",    "loadLocalDm": "danmaku.js",    "segDmDecode": "danmaku.js",    "danmakuFormat": "danmaku.js",    "onlineDanmaku": "danmaku.js",    "loadCommandDm": "commandDm.js",    "urlInputCheck": "urlInputCheck.js",    "midcrc": "crc32.js",    "crc32": "crc32.js",    "md5": "md5.js",    "RebuildPlayerurl": "rebuildPlayerurl.js",    "urlsign": "sign.js",    "observerAddedNodes": "nodeObserver.js",    "removeObserver": "nodeObserver.js",    "switchVideo": "switchVideo.js",    "closedCaption": "closedCaption.js",    "segProgress": "segProgress.js",    "localMedia": "localMedia.js",    "allDanmaku": "allDanmaku.js",    "bezier": "cubicBezier",    "element": "element.js",    "getCss": "element.js",    "saveAs": "extend.js",    "readAs": "extend.js",    "Base64": "Base64.js",    "getAidInfo": "extend.js",    "downloadThis": "download.js",    "getJson": "url.js",    "aria2": "aria2.js",    "ef2": "ef2.js",    "getUrlValue": "extend.js",    "showAccesskey": "accesskey.js",    "strSize": "extend.js",    "intervalFormat": "extend.js",    "runWhile": "extend.js",    "bofqiMessage": "extend.js",    "alertMessage": "extend.js"};
    modules["bug.json"] = [    "__PGC_USERSTATE__",    "__BILI_CONFIG__",    "__mobxGlobals",    "__mobxInstanceCount",    "_babelPolyfill",    "BilibiliPlayer",    "BiliJsBridge",    "BPlayer",    "BwpElement",    "BwpMediaSource",    "bbComment",    "bPlayer",    "EmbedPlayer",    "GrayManager",    "PlayerAgent",    "PlayerSetOnline",    "abtest",    "ad_rp",    "ad_url",    "bPlayer",    "bsourceFrom",    "dashjs",    "deltaFilter",    "directiveDispatcher",    "ep",    "flashChecker",    "flvjs",    "getAuthorInfo",    "getCookie",    "getIEVersion",    "gqs",    "heimu",    "insertLink",    "insertScript",    "iris",    "isBiliPlayer",    "isEmbedPlayer",    "isInit",    "jsurl",    "jsUrls",    "loadLink",    "loadScript",    "loginInfoCallbacks",    "md",    "nano",    "nanoWidgetsJsonp",    "player",    "playerInfo",    "player_fullwin",    "player_widewin",    "rec_rp",    "regeneratorRuntime",    "reportConfig",    "reportFistAdFs",    "reportObserver",    "setSize",    "setSizeStyle",    "spmReportData",    "vd",    "videoWidgetsJsonP",    "webAbTest",    "webpackJsonp",    "webpackJsonpwebpackLogReporter",    "webpackLogReporter"];
    modules["mid.json"] = {    "code": 0,    "data": {        "birthday": "1980-01-01",        "coins": 0,        "face": "http://i2.hdslb.com/bfs/face/9f10323503739e676857f06f5e4f5eb323e9f3f2.jpg",        "fans_badge": false,        "is_followed": true,        "jointime": 1436351229,        "level": 6,        "mid": "11783021",        "moral": 0,        "name": "哔哩哔哩番剧出差",        "official": {            "type": 1,            "desc": "哔哩哔哩番剧出差 官方账号"        },        "pendant": {            "pid": 0,            "name": "",            "image": "",            "expire": 0        },        "rank":            "10000",        "sex": "保密",        "sign": "",        "silence": 0,        "sys_notice": {},        "theme": {},        "user_honour_info": {            "colour": null,            "mid": 0,            "tags": null        },        "vip": {            "avatar_subscript": 1,            "avatar_subscript_url": "http://i0.hdslb.com/bfs/vip/icon_Certification_big_member_22_3x.png",            "due_date": 1655740800000,            "label": {                "bg_color": "#FB7299",                "bg_style": 1,                "border_color": "",                "label_theme": "annual_vip",                "path": "",                "text": "年度大会员",                "text_color": "#FFFFFF"            },            "nickname_color": "#FB7299",            "role": 3,            "status": 1,            "theme_type": 0,            "type": 2, "vip_pay_type": 1        }    },    "message": "0",    "ttl": 1};
    modules["protobuf.json"] = {    "nested": {        "bilibili": {            "nested": {                "DmWebViewReply": {                    "fields": {                        "state": {                            "type": "int32",                            "id": 1                        },                        "text": {                            "type": "string",                            "id": 2                        },                        "textSide": {                            "type": "string",                            "id": 3                        },                        "dmSge": {                            "type": "DmSegConfig",                            "id": 4                        },                        "flag": {                            "type": "DanmakuFlagConfig",                            "id": 5                        },                        "specialDms": {                            "rule": "repeated",                            "type": "string",                            "id": 6                        },                        "checkBox": {                            "type": "bool",                            "id": 7                        },                        "count": {                            "type": "int64",                            "id": 8                        },                        "commandDms": {                            "rule": "repeated",                            "type": "CommandDm",                            "id": 9                        },                        "dmSetting": {                            "type": "DanmuWebPlayerConfig",                            "id": 10                        }                    }                },                "CommandDm": {                    "fields": {                        "id": {                            "type": "int64",                            "id": 1                        },                        "oid": {                            "type": "int64",                            "id": 2                        },                        "mid": {                            "type": "int64",                            "id": 3                        },                        "command": {                            "type": "string",                            "id": 4                        },                        "content": {                            "type": "string",                            "id": 5                        },                        "progress": {                            "type": "int32",                            "id": 6                        },                        "ctime": {                            "type": "string",                            "id": 7                        },                        "mtime": {                            "type": "string",                            "id": 8                        },                        "extra": {                            "type": "string",                            "id": 9                        },                        "idStr": {                            "type": "string",                            "id": 10                        }                    }                },                "DmSegConfig": {                    "fields": {                        "pageSize": {                            "type": "int64",                            "id": 1                        },                        "total": {                            "type": "int64",                            "id": 2                        }                    }                },                "DanmakuFlagConfig": {                    "fields": {                        "recFlag": {                            "type": "int32",                            "id": 1                        },                        "recText": {                            "type": "string",                            "id": 2                        },                        "recSwitch": {                            "type": "int32",                            "id": 3                        }                    }                },                "DmSegMobileReply": {                    "fields": {                        "elems": {                            "rule": "repeated",                            "type": "DanmakuElem",                            "id": 1                        }                    }                },                "DanmakuElem": {                    "fields": {                        "id": {                            "type": "int64",                            "id": 1                        },                        "progress": {                            "type": "int32",                            "id": 2                        },                        "mode": {                            "type": "int32",                            "id": 3                        },                        "fontsize": {                            "type": "int32",                            "id": 4                        },                        "color": {                            "type": "uint32",                            "id": 5                        },                        "midHash": {                            "type": "string",                            "id": 6                        },                        "content": {                            "type": "string",                            "id": 7                        },                        "ctime": {                            "type": "int64",                            "id": 8                        },                        "weight": {                            "type": "int32",                            "id": 9                        },                        "action": {                            "type": "string",                            "id": 10                        },                        "pool": {                            "type": "int32",                            "id": 11                        },                        "idStr": {                            "type": "string",                            "id": 12                        },                        "attr": {                            "type": "int32",                            "id": 13                        }                    }                },                "DanmuWebPlayerConfig": {                    "fields": {                        "dmSwitch": {                            "type": "bool",                            "id": 1                        },                        "aiSwitch": {                            "type": "bool",                            "id": 2                        },                        "aiLevel": {                            "type": "int32",                            "id": 3                        },                        "blocktop": {                            "type": "bool",                            "id": 4                        },                        "blockscroll": {                            "type": "bool",                            "id": 5                        },                        "blockbottom": {                            "type": "bool",                            "id": 6                        },                        "blockcolor": {                            "type": "bool",                            "id": 7                        },                        "blockspecial": {                            "type": "bool",                            "id": 8                        },                        "preventshade": {                            "type": "bool",                            "id": 9                        },                        "dmask": {                            "type": "bool",                            "id": 10                        },                        "opacity": {                            "type": "float",                            "id": 11                        },                        "dmarea": {                            "type": "int32",                            "id": 12                        },                        "speedplus": {                            "type": "float",                            "id": 13                        },                        "fontsize": {                            "type": "float",                            "id": 14                        },                        "screensync": {                            "type": "bool",                            "id": 15                        },                        "speedsync": {                            "type": "bool",                            "id": 16                        },                        "fontfamily": {                            "type": "string",                            "id": 17                        },                        "bold": {                            "type": "bool",                            "id": 18                        },                        "fontborder": {                            "type": "int32",                            "id": 19                        },                        "drawType": {                            "type": "string",                            "id": 20                        }                    }                }            }        }    }};
    modules["videoSort.json"] = {    "1": [        1,        "动画",        "//www.bilibili.com/v/douga/"    ],    "3": [        3,        "音乐",        "//www.bilibili.com/v/music/"    ],    "29": [        3,        "音乐现场",        "//www.bilibili.com/v/music/live"    ],    "36": [        36,        "科技",        "//www.bilibili.com/v/technology"    ],    "75": [        217,        "动物综合",        "//www.bilibili.com/v/animal/animal_composite/"    ],    "76": [        211,        "美食制作",        "//www.bilibili.com/v/food/make/"    ],    "86": [        1,        "特摄",        "//www.bilibili.com/v/douga/"    ],    "95": [        188,        "数码",        "//www.bilibili.com/v/digital/mobile/"    ],    "129": [        129,        "舞蹈",        "//www.bilibili.com/v/dance"    ],    "155": [        155,        "时尚",        "//www.bilibili.com/v/fashion"    ],    "157": [        155,        "美妆护肤",        "//www.bilibili.com/v/fashion/makeup/"    ],    "158": [        155,        "穿搭",        "//www.bilibili.com/v/fashion/clothing/"    ],    "159": [        155,        "时尚潮流",        "//www.bilibili.com/v/fashion/trend/"    ],    "160": [        160,        "生活",        "//www.bilibili.com/v/life"    ],    "163": [        160,        "家居房产",        "//www.bilibili.com/v/life/home"    ],    "164": [        234,        "健身",        "//www.bilibili.com/v/sports/aerobics"    ],    "168": [        168,        "国创",        "//www.bilibili.com/guochuang"    ],    "176": [        223,        "汽车生活",        "//www.bilibili.com/v/car/life/"    ],    "188": [        188,        "数码",        "//www.bilibili.com/v/digital"    ],    "189": [        188,        "电脑装机",        "//www.bilibili.com/v/digital/pc"    ],    "190": [        188,        "数码摄影",        "//www.bilibili.com/v/digital/photography"    ],    "191": [        188,        "影音智能",        "//www.bilibili.com/v/digital/intelligence_av"    ],    "192": [        155,        "风尚标",        "//www.bilibili.com/v/fashion/trends"    ],    "193": [        3,        "MV",        "//www.bilibili.com/v/music/mv"    ],    "194": [        3,        "电音",        "//www.bilibili.com/v/music/electronic"    ],    "195": [        168,        "动态漫·广播剧",        "//www.bilibili.com/v/guochuang/motioncomic"    ],    "198": [        129,        "街舞",        "//www.bilibili.com/v/dance/hiphop"    ],    "199": [        129,        "明星舞蹈",        "//www.bilibili.com/v/dance/star"    ],    "200": [        129,        "中国舞",        "//www.bilibili.com/v/dance/china"    ],    "201": [        36,        "科学科普",        "//www.bilibili.com/v/technology/science"    ],    "202": [        202,        "资讯",        "//www.bilibili.com/v/information/"    ],    "203": [        202,        "热点",        "//www.bilibili.com/v/information/hotspot/"    ],    "204": [        202,        "环球",        "//www.bilibili.com/v/information/global/"    ],    "205": [        202,        "社会",        "//www.bilibili.com/v/information/social/"    ],    "206": [        202,        "综合",        "//www.bilibili.com/v/information/multiple/"    ],    "207": [        36,        "财经",        "//www.bilibili.com/v/technology/finance"    ],    "208": [        36,        "校园学习",        "//www.bilibili.com/v/technology/campus"    ],    "209": [        36,        "职业职场",        "//www.bilibili.com/v/technology/career"    ],    "210": [        1,        "手办·模玩",        "//www.bilibili.com/v/douga/garage_kit"    ],    "211": [        211,        "美食",        "//www.bilibili.com/v/food"    ],    "212": [        211,        "美食侦探",        "//www.bilibili.com/v/food/detective/"    ],    "213": [        211,        "美食测评",        "//www.bilibili.com/v/food/measurement/"    ],    "214": [        211,        "田园美食",        "//www.bilibili.com/v/food/rural/"    ],    "215": [        211,        "美食记录",        "//www.bilibili.com/v/food/record/"    ],    "216": [        119,        "鬼畜剧场",        "//www.bilibili.com/v/kichiku/theatre/"    ],    "217": [        217,        "动物圈",        "//www.bilibili.com/v/animal"    ],    "218": [        217,        "喵星人",        "//www.bilibili.com/v/animal/cat/"    ],    "219": [        217,        "汪星人",        "//www.bilibili.com/v/animal/dog/"    ],    "220": [        217,        "大熊猫",        "//www.bilibili.com/v/animal/panda/"    ],    "221": [        217,        "野生动物",        "//www.bilibili.com/v/animal/wild_animal/"    ],    "222": [        217,        "爬宠",        "//www.bilibili.com/v/animal/reptiles/"    ],    "223": [        223,        "汽车",        "//www.bilibili.com/v/car"    ],    "224": [        223,        "汽车文化",        "//www.bilibili.com/v/car/culture/"    ],    "225": [        223,        "汽车极客",        "//www.bilibili.com/v/car/geek/"    ],    "226": [        223,        "智能出行",        "//www.bilibili.com/v/car/smart/"    ],    "227": [        223,        "购车攻略",        "//www.bilibili.com/v/car/strategy/"    ],    "228": [        36,        "人文历史",        "//www.bilibili.com/v/knowledge/humanity_history/"    ],    "229": [        36,        "设计·创意",        "//www.bilibili.com/v/knowledge/design/"    ],    "230": [        188,        "软件应用",        "//www.bilibili.com/v/tech/application/"    ],    "231": [        188,        "计算机技术",        "//www.bilibili.com/v/tech/computer_tech/"    ],    "232": [        188,        "工业·工程·机械",        "//www.bilibili.com/v/tech/computer_tech/"    ],    "233": [        188,        "极客DIY",        "//www.bilibili.com/v/tech/diy/"    ],    "234": [        234,        "运动",        "//www.bilibili.com/v/sports"    ],    "235": [        234,        "篮球·足球",        "//www.bilibili.com/v/sports/basketballfootball"    ],    "236": [        234,        "竞技体育",        "//www.bilibili.com/v/sports/athletic"    ],    "237": [        234,        "运动文化",        "//www.bilibili.com/v/sports/culture"    ],    "238": [        234,        "运动综合",        "//www.bilibili.com/v/sports/comprehensive"    ],    "240": [        223,        "摩托车",        "//www.bilibili.com/v/car/motorcycle"    ]};
    modules["aria2.js"] = "/**\n * 本模块负责与aria2通信并构造下载数据\n */\n(function () {\n    try {\n        class Aria2 {\n            constructor() {\n                this.setting = {};\n                config.useragent && (this.setting.userAgent = config.useragent);\n                config.referer && (this.setting.referer = config.referer);\n                config.filepath && (this.setting.directory = config.filepath);\n                config.rpcToken && (this.setting.token = config.rpcToken);\n            }\n            shell(obj) {\n                return new Promise((r, j) => {\n                    let result = \"aria2c\";\n                    obj = { ...this.setting, ...obj };\n                    obj.urls.forEach(d => result += ` \"${d}\"`);\n                    obj.out && (result += ` --out=\"${obj.out}\"`);\n                    obj.userAgent && (result += ` --user-agent=\"${obj.userAgent}\"`);\n                    obj.referer && (result += ` --referer=\"${obj.referer}\"`);\n                    obj.directory && (result += ` --dir=\"${obj.directory}\"`);\n                    obj.split && (result += ` --split=\"${obj.split}\"`);\n                    obj.header && Object.entries(obj.header).forEach(d => result += ` --header=\"${d[0]}: ${d[1]}\"`);\n                    navigator.clipboard.writeText(result).then(r, e => j(e));\n                });\n            }\n            rpc(obj) {\n                obj = { ...this.setting, ...obj };\n                const options = {};\n                obj.out && (options.out = obj.out);\n                obj.userAgent && (options[\"user-agent\"] = obj.userAgent);\n                obj.referer && (options[\"referer\"] = obj.referer);\n                obj.directory && (options[\"dir\"] = obj.directory);\n                obj.split && (options[\"split\"] = obj.split);\n                obj.header && (options[\"header\"] = obj.header);\n                return this.postMessage(\"aria2.addUri\", obj.id || new Date().getTime(), [obj.urls, options]);\n            }\n            postMessage(method, id, params = []) {\n                const url = `${config.rpcServer}:${config.rpcPort}/jsonrpc`;\n                config.rpcToken && params.unshift(`token:${config.rpcToken}`);\n                return new Promise((r, j) => {\n                    xhr({\n                        url: url,\n                        method: \"POST\",\n                        responseType: \"json\",\n                        data: JSON.stringify({ method, id, params })\n                    }).then(d => {\n                        d.error && j(d.error);\n                        d.result && r(d.result);\n                    }).catch(e => {\n                        xhr({\n                            url: API.objUrl(url, { method, id, params: API.Base64.encode(JSON.stringify(params)) }),\n                            method: \"GET\",\n                            responseType: \"json\"\n                        }).then(d => {\n                            d.error && j(d.error);\n                            d.result && r(d.result);\n                        }).catch(() => j(e));\n                    });\n                });\n            }\n            getVersion() {\n                return this.postMessage(\"aria2.getVersion\", new Date().getTime());\n            }\n        }\n        API.aria2 = {\n            shell: (obj) => new Aria2().shell(obj),\n            rpcTest: () => new Aria2().getVersion(),\n            rpc: (obj) => new Aria2().rpc(obj)\n        };\n    }\n    catch (e) {\n        toast.error(\"aria2.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/download/aria2.js";
    modules["contentMenu.js"] = "/**\n * 添加下载右键菜单\n */\n(function () {\n    API.switchVideo(() => {\n        var _a, _b;\n        try {\n            const li = document.createElement(\"li\");\n            li.innerHTML = '<a id=\"BLOD-dl-content\" class=\"context-menu-a js-action\" href=\"javascript:void(0);\">下载视频</a>';\n            li.setAttribute(\"class\", \"context-line context-menu-function bili-old-download\");\n            li.onmouseover = () => li.setAttribute(\"class\", \"context-line context-menu-function bili-old-download hover\");\n            li.onmouseout = () => li.setAttribute(\"class\", \"context-line context-menu-function bili-old-download\");\n            li.onclick = () => API.downloadThis();\n            let flag = 0;\n            (_a = document.querySelector(\"#bilibiliPlayer\")) === null || _a === void 0 ? void 0 : _a.addEventListener(\"DOMNodeInserted\", e => {\n                if (!flag && e.target.className && /context-line context-menu-function/.test(e.target.className)) {\n                    const node = document.querySelector(\".bilibili-player-context-menu-container.black\");\n                    flag = setTimeout(() => {\n                        if (node.querySelector(\".context-menu-danmaku\"))\n                            return;\n                        if (node.querySelector(\"#BLOD-dl-content\"))\n                            return;\n                        if (node.contains(li))\n                            return;\n                        node.firstChild.appendChild(li);\n                    }, 100);\n                }\n            });\n            (_b = document.querySelector(\"#bilibiliPlayer\")) === null || _b === void 0 ? void 0 : _b.addEventListener(\"DOMNodeRemoved\", e => {\n                if (flag && e.target.className && /context-line context-menu-function/.test(e.target.className)) {\n                    flag = 0;\n                    try {\n                        li.remove();\n                    }\n                    catch (_a) { }\n                    ;\n                }\n            });\n        }\n        catch (e) {\n            toast.error(\"dlContentMenu.js\", e);\n        }\n    });\n})();\n\n//# sourceURL=API://@bilibili/dist/download/contentMenu.js";
    modules["download.js"] = "/**\n * 本模块负责下载功能,主要是视频下载功能\n */\n(function () {\n    try {\n        class Download {\n            constructor() {\n                /**\n                 * 已获取类型列表\n                 */\n                this.type = [];\n                /**\n                 * 整理出的链接列表\n                 */\n                this.links = [];\n                /**\n                 * url序号对应的质量信息\n                 */\n                this.quality = {\n                    30280: \"320Kbps\",\n                    30250: \"ATMOS\",\n                    30232: \"128Kbps\",\n                    30216: \"64Kbps\",\n                    30127: \"8K\",\n                    30126: \"Dolby\",\n                    30125: \"HDR\",\n                    30121: \"4K\",\n                    30120: \"4K\",\n                    30116: '1080P60',\n                    30112: '1080P+',\n                    30106: '1080P+',\n                    30102: '1080P+',\n                    30080: '1080P',\n                    30077: '1080P',\n                    30076: '720P',\n                    30074: '720P',\n                    30066: '720P',\n                    30064: '720P',\n                    30048: \"720P\",\n                    30033: '480P',\n                    30032: '480P',\n                    30016: '360P',\n                    30015: '360P',\n                    30011: '360P',\n                    464: '预览',\n                    208: \"1080P\",\n                    192: \"720P\",\n                    160: \"480P\",\n                    127: \"8K\",\n                    126: \"Dolby\",\n                    125: \"HDR\",\n                    120: \"4K\",\n                    116: \"1080P60\",\n                    112: \"1080P+\",\n                    80: \"1080P\",\n                    74: \"720P60\",\n                    64: \"720P\",\n                    48: \"720P\",\n                    32: \"480P\",\n                    16: \"360P\",\n                    15: \"360P\"\n                };\n                /**\n                 * 视频编码信息对应的id,可能不完整\n                 */\n                this.codec = {\n                    hev: [30126, 30125, 30121, 30102, 30077, 30066, 30033, 30011],\n                    avc: [30120, 30112, 30080, 30064, 30032, 30016]\n                };\n                /**\n                 * 颜色表\n                 */\n                this.color = {\n                    \"8K\": \"background-color: #ffe42b;background-image: linear-gradient(to right, #ffe42b, #dfb200);\",\n                    \"Dolby\": \"background-color: #ffe42b;background-image: linear-gradient(to right, #ffe42b, #dfb200);\",\n                    \"ATMOS\": \"background-color: #ffe42b;background-image: linear-gradient(to right, #ffe42b, #dfb200);\",\n                    \"HDR\": \"background-color: #ffe42b;background-image: linear-gradient(to right, #ffe42b, #dfb200);\",\n                    \"4K\": \"background-color: #c0f;background-image: linear-gradient(to right, #c0f, #90f);\",\n                    \"1080P60\": \"background-color: #c0f;background-image: linear-gradient(to right, #c0f, #90f);\",\n                    \"1080P+\": \"background-color: #f00;background-image: linear-gradient(to right, #f00, #c00);\",\n                    \"1080P\": \"background-color: #f00;background-image: linear-gradient(to right, #f00, #c00);\",\n                    \"720P60\": \"background-color: #f90;background-image: linear-gradient(to right, #f90, #d70);\",\n                    \"720P\": \"background-color: #f90;background-image: linear-gradient(to right, #f90, #d70);\",\n                    \"480P\": \"background-color: #00d;background-image: linear-gradient(to right, #00d, #00a);\",\n                    \"360P\": \"background-color: #0d0;\",\n                    \"mp4\": \"background-color: #e0e;\",\n                    \"avc\": \"background-color: #07e;\",\n                    \"hev\": \"background-color: #7ba;\",\n                    \"aac\": \"background-color: #07e;\",\n                    \"flv\": \"background-color: #0dd;\",\n                    \"320Kbps\": \"background-color: #f00;background-image: linear-gradient(to right, #f00, #c00);\",\n                    \"128Kbps\": \"background-color: #f90;background-image: linear-gradient(to right, #f90, #d70);\",\n                    \"64Kbps\": \"background-color: #0d0;\"\n                };\n                // 切P后清除下载数据并移除下载面板\n                API.switchVideo(() => { this.type = []; this.links = []; this.table && this.table.remove(); });\n            }\n            /**\n             * 整理playurl返回值并提取其中的媒体链接记录到links\n             * @param playinfo ajax返回的JSON数据\n             */\n            decodePlayinfo(playinfo) {\n                playinfo.data && this.decodePlayinfo(playinfo.data);\n                playinfo.result && this.decodePlayinfo(playinfo.result);\n                playinfo.durl && this.durl(playinfo.durl);\n                playinfo.dash && this.dash(playinfo.dash);\n            }\n            /**\n             * 根据url确定画质/音质信息\n             * 需要维护quality表\n             * @param url 多媒体url\n             * @param id 媒体流id\n             * @returns 画质/音质信息\n             */\n            getQuality(url, id) {\n                return this.quality[this.getID(url)] || (id && this.quality[id]) || \"N/A\";\n            }\n            /**\n             * 从url中提取可能的id\n             * @param url 多媒体url\n             */\n            getID(url) {\n                return Number(/[0-9]+\\.((flv)|(mp4)|(m4s))/.exec(url)[0].split(\".\")[0]);\n            }\n            /**\n             * 整理dash部分\n             * @param dash dash信息\n             */\n            dash(dash) {\n                dash.video && this.dashVideo(dash.video, dash.duration);\n                dash.audio && this.dashAudio(dash.audio, dash.duration);\n                dash.dolby && dash.dolby.audio && Array.isArray(dash.dolby.audio) && this.dashATMOS(dash.dolby.audio, dash.duration);\n            }\n            /**\n             * 整理dash视频部分\n             * @param video dash视频信息\n             * @param duration duration信息,配合bandwidth能计算出文件大小\n             */\n            dashVideo(video, duration) {\n                video.forEach(d => {\n                    const url = d.baseUrl || d.base_url;\n                    let type = \"\";\n                    if (!url)\n                        return;\n                    if (d.codecs)\n                        switch (d.codecs.includes(\"avc\")) {\n                            case true:\n                                type = \"avc\";\n                                break;\n                            case false:\n                                type = \"hev\";\n                                break;\n                        }\n                    else {\n                        const id = this.getID(url);\n                        type = this.codec.hev.find(d => d === id) ? \"hev\" : \"avc\";\n                    }\n                    !this.type.includes(\"dash\") && this.type.push(\"dash\");\n                    this.links.push({\n                        type: type,\n                        url: url,\n                        quality: this.getQuality(url, d.id),\n                        size: API.sizeFormat(d.bandwidth * duration / 8),\n                        backupUrl: d.backupUrl || d.backup_url\n                    });\n                });\n            }\n            /**\n             * 整理dash音频部分\n             * @param audio dash音频信息\n             * @param duration duration信息,配合bandwidth能计算出文件大小\n             */\n            dashAudio(audio, duration) {\n                audio.forEach(d => {\n                    const url = d.baseUrl || d.base_url;\n                    url && this.links.push({\n                        type: \"aac\",\n                        url: url,\n                        quality: this.getQuality(url, d.id),\n                        size: API.sizeFormat(d.bandwidth * duration / 8),\n                        backupUrl: d.backupUrl || d.backup_url\n                    });\n                });\n            }\n            /**\n             * 整理dash杜比全景声部分\n             * @param audio 杜比全景声信息\n             * @param duration duration信息,配合bandwidth能计算出文件大小\n             */\n            dashATMOS(audio, duration) {\n                audio.forEach(d => {\n                    const url = d.baseUrl || d.base_url;\n                    url && this.links.push({\n                        type: \"aac\",\n                        url: url,\n                        quality: this.getQuality(url, d.id),\n                        size: API.sizeFormat(d.bandwidth * duration / 8),\n                        backupUrl: d.backupUrl || d.backup_url\n                    });\n                });\n            }\n            /**\n             * 整理durl部分\n             * @param durl durl信息\n             */\n            durl(durl) {\n                let index = 0; // flv分段标记\n                durl.forEach(d => {\n                    const link = {\n                        type: \"\",\n                        url: d.url,\n                        quality: this.getQuality(d.url, d.id),\n                        size: API.sizeFormat(d.size),\n                        backupUrl: d.backupUrl || d.backup_url\n                    };\n                    switch (d.url.includes(\"mp4?\")) {\n                        case true:\n                            link.type = \"mp4\";\n                            !this.type.includes(\"mp4\") && this.type.push(\"mp4\");\n                            break;\n                        case false:\n                            link.type = \"flv\";\n                            index++;\n                            link.flvSplit = index;\n                            !this.type.includes(\"flv\") && this.type.push(\"flv\");\n                            break;\n                    }\n                    this.links.push(link);\n                });\n            }\n            /**\n             * 右键下载响应\n             */\n            async contentMenu() {\n                if (API.aid && API.cid) {\n                    if (!this.links[0]) {\n                        API.__playinfo__ && this.decodePlayinfo(API.__playinfo__);\n                        const result = await Promise.all(config.downloadList.reduce((s, d) => {\n                            !this.type.includes(d) && s.push(this.getContent(d));\n                            return s;\n                        }, []));\n                        result.forEach(d => d && this.decodePlayinfo(d));\n                        await this.getOther();\n                    }\n                    const title = this.getTitle();\n                    this.links.forEach(d => {\n                        !d.filename && (d.filename = title);\n                    });\n                    this.showTable();\n                }\n            }\n            async getOther() {\n                var _a;\n                if (!config.ifDlDmCC)\n                    return;\n                if (API.danmaku) {\n                    const url = config.dlDmType == \"json\" ? JSON.stringify(API.danmaku, undefined, \"\\t\") : API.toXml(API.danmaku);\n                    this.links.push({\n                        url: url,\n                        type: \"其他\",\n                        quality: \"弹幕\",\n                        size: API.sizeFormat(API.strSize(url)),\n                        filename: `${this.getTitle()}-${API.cid}.${config.dlDmType}`\n                    });\n                }\n                if (API.subtitle) {\n                    API.subtitle.forEach(d => {\n                        this.links.push({\n                            url: !d.subtitle_url.includes(\":\") ? d.subtitle_url.replace(\"//\", \"https://\") : d.subtitle_url,\n                            type: \"其他\",\n                            quality: d.lan_doc,\n                            size: \"N/A\"\n                        });\n                    });\n                }\n                const data = await API.getAidInfo(API.aid);\n                data && ((_a = data === null || data === void 0 ? void 0 : data.View) === null || _a === void 0 ? void 0 : _a.pic) && this.links.push({\n                    url: data.View.pic,\n                    type: \"其他\",\n                    quality: \"封面\",\n                    size: \"N/A\",\n                    amylose: true\n                });\n            }\n            /**\n             * 封装请求链接\n             * 用于过滤Promise.all请求错误\n             * @param d 请求类型\n             * @returns 请求结果\n             */\n            async getContent(d) {\n                let result;\n                try {\n                    switch (d) {\n                        case \"dash\":\n                            result = API.pgc ?\n                                await API.getJson(\"api.bilibili.com/pgc/player/web/playurl\", { avid: API.aid, cid: API.cid, fnver: 0, fnval: 2000 }, true) :\n                                await API.getJson(\"api.bilibili.com/x/player/playurl\", { avid: API.aid, cid: API.cid, fnver: 0, fnval: 2000 }, true);\n                            break;\n                        case \"flv\":\n                            result = API.pgc ?\n                                await API.getJson(\"api.bilibili.com/pgc/player/web/playurl\", { avid: API.aid, cid: API.cid }, true) :\n                                await API.getJson(\"api.bilibili.com/x/player/playurl\", { avid: API.aid, cid: API.cid }, true);\n                            break;\n                        case \"mp4\":\n                            result = API.pgc ?\n                                await API.getJson(\"api.bilibili.com/pgc/player/api/playurlproj\", { cid: API.cid }, true) :\n                                await API.getJson(\"app.bilibili.com/v2/playurlproj\", { cid: API.cid }, true);\n                            break;\n                    }\n                }\n                catch (e) { }\n                return result;\n            }\n            /**\n             * 呼出下载面板\n             */\n            showTable() {\n                if (!this.links[0])\n                    return toast.warning(\"未获取到任何下载数据!\");\n                this.table && this.table.remove();\n                this.table = API.addElement(\"div\");\n                const real = this.table.attachShadow({ mode: \"closed\" });\n                const root = API.addElement(\"div\", { class: \"table\" }, real);\n                const cells = {};\n                API.element.clickRemove(this.table);\n                API.addCss(API.getCss(\"download.css\"), undefined, real);\n                this.links.forEach(d => {\n                    const cell = cells[d.type] || API.addElement(\"div\", { class: \"cell\" }, root);\n                    if (!cells[d.type]) {\n                        cells[d.type] = cell;\n                        const div = API.addElement(\"div\", { class: \"type\" }, cell, d.type);\n                        this.color[d.type] && div.setAttribute(\"style\", this.color[d.type]);\n                    }\n                    const item = API.addElement(\"a\", { class: \"item\", target: \"_blank\" }, cell);\n                    const up = API.addElement(\"div\", { class: \"up\" }, item, d.quality + (d.flvSplit ? \"x\" + d.flvSplit : \"\"));\n                    this.color[d.quality] && up.setAttribute(\"style\", this.color[d.quality]);\n                    API.addElement(\"div\", { class: \"down\" }, item, d.size);\n                    d.amylose ? item.href = d.url : (item.onclick = () => {\n                        /^https?:\\/\\/([\\w-]+\\.)+[\\w-]+(\\/[\\w-,.\\/?%&=]*)?/.test(d.url) ?\n                            this.postData(d) :\n                            API.saveAs(d.url, d.filename || `download ${API.timeFormat(undefined, true)}.txt`, d.contentType || \"text/plain\");\n                    });\n                });\n            }\n            postData(data) {\n                !Reflect.has(data, \"_name\") && (data.filename = this.setFinalName(data));\n                switch (config.downloadMethod) {\n                    case \"ef2\":\n                        API.ef2({ url: data.url, out: data.filename });\n                        break;\n                    case \"aria2\":\n                        API.aria2.shell({ urls: [data.url], out: data.filename })\n                            .then(() => toast.success(`已复制aria2命令行到剪切板,在cmd等shell中使用即可下载~`))\n                            .catch(e => toast.error(`复制aria2命令行失败!`, e));\n                        break;\n                    case \"aira2 RPC\":\n                        API.aria2.rpc({ urls: [data.url], out: data.filename })\n                            .then(GID => toast.success(`已添加下载任务到aria2 RPC主机,任务GID:${GID}`))\n                            .catch(e => toast.error(`添加下载任务到aria2 RPC主机出错!`, e));\n                        break;\n                    default: this.rightKey(data);\n                }\n            }\n            /**\n             * 获取当前视频标题\n             * @returns 标题\n             */\n            getTitle() {\n                const title = document.title.split(\"_哔哩\")[0];\n                const p = location.href.includes(\"p=\") ? location.href.match(/p=\\d+/)[0].split(\"=\")[1] : \"\";\n                return p ? title + p : title;\n            }\n            /**\n             * 从URL中提取可能的文件名和拓展名\n             * @param url\n             * @returns [文件名,拓展名]\n             */\n            getUrlFileName(url) {\n                url = url.split(\"?\")[0];\n                const arr = url.split(\"/\");\n                return arr[arr.length - 1].split(\".\");\n            }\n            /**\n             * 合成最终文件名\n             * @param obj.url 下载url,从中提取可能的文件名,优先级最低\n             * @param obj.type 下载资源类型,用于决定后缀名,优先级次之\n             * @param obj.filename 预设定文件名,优先级最高\n             * @returns 文件名\n             */\n            setFinalName(obj) {\n                let adv = \"\";\n                let arr = this.getUrlFileName(obj.url);\n                let ars = obj.filename.split(\".\");\n                switch (obj.type) {\n                    case \"mp4\":\n                        adv = \".mp4\";\n                        break;\n                    case \"flv\":\n                        adv = \".flv\";\n                        break;\n                    case \"aac\":\n                        adv = \".m4a\";\n                        break;\n                    case \"avc\":\n                        adv = \".avc.m4v\";\n                        break;\n                    case \"hev\":\n                        adv = \".hevc.m4v\";\n                        break;\n                }\n                adv = ars[1] ? `.${ars.pop()}` : adv ? adv : arr[1] ? `.${arr.pop()}` : \"\";\n                Reflect.set(obj, \"_name\", true);\n                return (obj.filename || arr[0]) + `${obj.flvSplit ? \"x\" + obj.flvSplit : \"\"}.${obj.quality}${adv}`;\n            }\n            /**\n             * 右键下载\n             * @param data 下载数据\n             */\n            rightKey(data) {\n                const root = API.element.popupbox({ width: \"300px\" });\n                API.addElement(\"div\", { style: \"text-align: center;font-weight: bold;padding-block-end: 10px;\" }, root, data.filename);\n                API.addElement(\"div\", { style: \"padding-block-end: 10px;\" }, root, `<a href=${data.url} target=\"_blank\" download=\"${data.filename}\">请在此处右键“另存为”以保存文件,IDM的话也可以右键“使用 IDM下载链接”。</a>`);\n                API.addElement(\"div\", { style: \"font-size: 10px; padding-block-end: 10px;\" }, root, '本方式下载不太稳定,不嫌麻烦的话可在设置中更换下载方式。');\n            }\n        }\n        const download = new Download();\n        API.downloadThis = () => download.contentMenu();\n    }\n    catch (e) {\n        toast.error(e, \"download.js\");\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/download/download.js";
    modules["ef2.js"] = "/**\n * 本模块负责使用ef2自定义协议调用IDM进行下载\n * 使用本下载方式需要先安装IDM{@see Internet Download Manager (IDM) {@link http://www.internetdownloadmanager.com/}}\n * 然后安装ef2工具{@see ef2 {@link https://github.com/MotooriKashin/ef2/releases/latest}}\n */\n(function () {\n    class Ef2 {\n        constructor() {\n            this.setting = {};\n            config.useragent && (this.setting.userAgent = config.useragent);\n            config.referer && (this.setting.referer = config.referer);\n            config.filepath && (this.setting.directory = config.filepath);\n            config.IDMLater && (this.setting.sendToList = config.IDMLater);\n            config.IDMToast && (this.setting.toastDisabled = config.IDMToast);\n        }\n        /**\n         * 发送下载数据到IDM\n         * @param data 配置IDM\n         */\n        sendLinkToIDM(data) {\n            data = { ...this.setting, ...data };\n            const a = document.createElement(\"a\");\n            a.href = this.encode(data);\n            a.click();\n        }\n        /**\n         * 编码ef2协议\n         * @param data 配置数据\n         * @returns ef2协议\n         */\n        encode(data) {\n            let result = \"\";\n            Object.keys(data).forEach((d) => {\n                switch (d) {\n                    case \"cookies\":\n                        result += ` -c \"${data.cookies}\"`;\n                        break;\n                    case \"directory\":\n                        data.directory = data.directory.replace(/\\//, \"\\\\\"); // 目录反斜杠可能误输入为了正斜杠\n                        data.directory && data.directory[data.directory.length - 1] == \"\\\\\" && (data.directory = data.directory.substr(0, data.directory.length - 1)); // 目录最后的反斜杠可能导致引号被转义 \n                        result += ` -o \"${data.directory}\"`;\n                        break;\n                    case \"out\":\n                        result += ` -s \"${data.out}\"`;\n                        break;\n                    case \"password\":\n                        result += ` -P \"${data.password}\"`;\n                        break;\n                    case \"postDate\":\n                        result += ` -d \"${data.postDate}\"`;\n                        break;\n                    case \"referer\":\n                        result += ` -r \"${data.referer}\"`;\n                        break;\n                    case \"sendToList\":\n                        result += ` -q`;\n                        break;\n                    case \"toastDisabled\":\n                        result += ` -f`;\n                        break;\n                    case \"url\":\n                        data.url.startsWith(\"//\") && (data.url = \"https:\" + data.url); // 省略协议头时默认添加http/tls头\n                        result += ` -u \"${data.url}\"`;\n                        break;\n                    case \"userAgent\":\n                        result += ` -a \"${data.userAgent}\"`;\n                        break;\n                    case \"userName\":\n                        result += ` -U \"${data.userName}\"`;\n                        break;\n                }\n            });\n            result && result.startsWith(\" \") && (result = result.substr(1, result.length));\n            return \"ef2://\" + API.Base64.encode(result);\n        }\n        /**\n         * 解码ef2链接为\n         * @param ef2ptl\n         * @returns ef2配置信息\n         */\n        decode(ef2ptl) {\n            ef2ptl = ef2ptl.replace(\"ef2://\", \"\");\n            ef2ptl = API.Base64.decode(ef2ptl) + \" \";\n            const key = ef2ptl.match(/-\\w /g);\n            const value = ef2ptl.split(/-\\w /);\n            value.shift();\n            return Array.from(key).reduce((s, d, i) => {\n                value[i] && value[i].endsWith(\" \") && (value[i] = value[i].substr(0, value[i].length - 1));\n                value[i] && value[i].endsWith(\"\\\"\") && (value[i] = value[i].substr(1, value[i].length - 2));\n                switch (d) {\n                    case \"-c \":\n                        s.cookies = value[i];\n                        break;\n                    case \"-o \":\n                        s.directory = value[i];\n                        break;\n                    case \"-s \":\n                        s.out = value[i];\n                        break;\n                    case \"-P \":\n                        s.password = value[i];\n                        break;\n                    case \"-d \":\n                        s.postDate = value[i];\n                        break;\n                    case \"-r \":\n                        s.referer = value[i];\n                        break;\n                    case \"-q \":\n                        s.sendToList = true;\n                        break;\n                    case \"-f \":\n                        s.toastDisabled = true;\n                        break;\n                    case \"-u \":\n                        s.url = value[i];\n                        break;\n                    case \"-a \":\n                        s.userAgent = value[i];\n                        break;\n                    case \"-U \":\n                        s.userName = value[i];\n                        break;\n                }\n                return s;\n            }, {});\n        }\n    }\n    // @ts-ignore EF2同时作为对象和方法\n    API.ef2 = (data) => new Ef2().sendLinkToIDM(data);\n    API.ef2.encode = (data) => new Ef2().encode(data);\n    API.ef2.decode = (ef2ptl) => new Ef2().decode(ef2ptl);\n})();\n\n//# sourceURL=API://@bilibili/dist/download/ef2.js";
    modules["abv.js"] = "/**\n * 本模块负责负责提供av/BV互转函数\n * 感谢知乎mcfx的回答,在其python代码基础上翻译为JavaScript,源链接如下\n * @see mcfx {@link https://www.zhihu.com/question/381784377/answer/1099438784}\n * */\n(function () {\n    try {\n        class Abv {\n            constructor() {\n                this.base58Table = 'fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF';\n                this.digitMap = [11, 10, 3, 8, 4, 6];\n                this.xor = 177451812;\n                this.add = 8728348608;\n                this.bvidTemplate = ['B', 'V', 1, '', '', 4, '', 1, '', 7, '', ''];\n                this.table = {};\n                for (let i = 0; i < 58; i++)\n                    this.table[this.base58Table[i]] = i;\n            }\n            /**\n             * av/BV互转\n             * @param input av或BV,可带av/BV前缀\n             * @returns 转化结果\n             */\n            check(input) {\n                if (/^[aA][vV][0-9]+$/.test(String(input)) || /^\\d+$/.test(String(input)))\n                    return this.avToBv(Number(/[0-9]+/.exec(String(input))[0]));\n                if (/^1[fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF]{9}$/.test(String(input)))\n                    return this.bvToAv(\"BV\" + input);\n                if (/^[bB][vV]1[fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF]{9}$/.test(String(input)))\n                    return this.bvToAv(String(input));\n                throw input;\n            }\n            bvToAv(BV) {\n                let r = 0;\n                for (let i = 0; i < 6; i++)\n                    r += this.table[BV[this.digitMap[i]]] * 58 ** i;\n                return (r - this.add) ^ this.xor;\n            }\n            avToBv(av) {\n                let bv = Array.from(this.bvidTemplate);\n                av = (av ^ this.xor) + this.add;\n                for (let i = 0; i < 6; i++)\n                    bv[this.digitMap[i]] = this.base58Table[parseInt(String(av / 58 ** i)) % 58];\n                return bv.join(\"\");\n            }\n        }\n        let abv = new Abv();\n        API.abv = (input) => abv.check(input);\n    }\n    catch (e) {\n        toast.error(\"abv.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/extensions/abv.js";
    modules["Base64.js"] = "/**\n * 本模块负责提供Base64<=>字符串的互转函数\n * 本模块核心代码直接来源如下\n * @see MDN Web Docs {@link https://developer.mozilla.org/en-US/docs/Glossary/Base64}\n */\n(function () {\n    try {\n        class Base64 {\n            static encode(str) {\n                return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {\n                    return String.fromCharCode(('0x' + p1));\n                }));\n            }\n            static decode(str) {\n                return decodeURIComponent(atob(str).split('').map(function (c) {\n                    return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);\n                }).join(''));\n            }\n        }\n        API.Base64 = {\n            encode: (str) => Base64.encode(str),\n            decode: (str) => Base64.decode(str)\n        };\n    }\n    catch (e) {\n        toast.error(\"base64.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/extensions/Base64.js";
    modules["crc32.js"] = "/**\n * 本模块提供CRC32散列算法及逆向工具,是将`BiliBili_crc2mid`修改为符合本项目模块规范的版本\n * 感谢`MoePus`提出的CRC32逆向算法,论坛原帖见\n * @see MoePus {@link https://moepus.oicp.net/2016/11/27/crccrack}\n * 感谢`esterTion`开源的该逆向算法的JavaScript版本,源项目信息如下\n * @see esterTion {@link https://github.com/esterTion/BiliBili_crc2mid}\n * @license GFUL\n */\n(function () {\n    try {\n        class Midcrc {\n            constructor() {\n                this.CRCPOLYNOMIAL = 0xEDB88320;\n                this.crctable = new Array(256);\n                this.index = new Array(4);\n                this.create_table();\n                API.midcrc = input => this.run(input);\n                API.crc32 = input => (((this.crc32(input) + 1) * -1) >>> 0).toString(16);\n            }\n            /**\n             * @param input 输入crc32散列值\n             * @returns 逆向出的mid值\n             */\n            run(input) {\n                let ht = parseInt('0x' + input) ^ 0xffffffff, snum, i, lastindex, deepCheckData;\n                for (i = 3; i >= 0; i--) {\n                    this.index[3 - i] = this.getcrcindex(ht >>> (i * 8));\n                    snum = this.crctable[this.index[3 - i]];\n                    ht ^= snum >>> ((3 - i) * 8);\n                }\n                for (i = 0; i < 10000000; i++) {\n                    lastindex = this.crc32lastindex(i);\n                    if (lastindex == this.index[3]) {\n                        deepCheckData = this.deepCheck(i, this.index);\n                        if (deepCheckData[0])\n                            break;\n                    }\n                }\n                if (i == 10000000)\n                    return -1;\n                return Number(i + '' + deepCheckData[1]);\n            }\n            create_table() {\n                let crcreg, i, j;\n                for (i = 0; i < 256; ++i) {\n                    crcreg = i;\n                    for (j = 0; j < 8; ++j) {\n                        if ((crcreg & 1) !== 0) {\n                            crcreg = this.CRCPOLYNOMIAL ^ (crcreg >>> 1);\n                        }\n                        else {\n                            crcreg >>>= 1;\n                        }\n                    }\n                    this.crctable[i] = crcreg;\n                }\n            }\n            crc32(input) {\n                if (typeof (input) != 'string')\n                    input = input.toString();\n                let crcstart = 0xFFFFFFFF, len = input.length, index;\n                for (let i = 0; i < len; ++i) {\n                    index = (crcstart ^ input.charCodeAt(i)) & 0xff;\n                    crcstart = (crcstart >>> 8) ^ this.crctable[index];\n                }\n                return crcstart;\n            }\n            crc32lastindex(input) {\n                if (typeof (input) != 'string')\n                    input = input.toString();\n                let crcstart = 0xFFFFFFFF, len = input.length, index;\n                for (let i = 0; i < len; ++i) {\n                    index = (crcstart ^ input.charCodeAt(i)) & 0xff;\n                    crcstart = (crcstart >>> 8) ^ this.crctable[index];\n                }\n                return index;\n            }\n            getcrcindex(t) {\n                for (let i = 0; i < 256; i++)\n                    if (this.crctable[i] >>> 24 == t)\n                        return i;\n                return -1;\n            }\n            deepCheck(i, index) {\n                let tc = 0x00, str = '', hash = this.crc32(i);\n                tc = hash & 0xff ^ index[2];\n                if (!(tc <= 57 && tc >= 48))\n                    return [0];\n                str += tc - 48;\n                hash = this.crctable[index[2]] ^ (hash >>> 8);\n                tc = hash & 0xff ^ index[1];\n                if (!(tc <= 57 && tc >= 48))\n                    return [0];\n                str += tc - 48;\n                hash = this.crctable[index[1]] ^ (hash >>> 8);\n                tc = hash & 0xff ^ index[0];\n                if (!(tc <= 57 && tc >= 48))\n                    return [0];\n                str += tc - 48;\n                hash = this.crctable[index[0]] ^ (hash >>> 8);\n                return [1, str];\n            }\n        }\n        new Midcrc();\n    }\n    catch (e) {\n        toast.error(\"crc32.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/extensions/crc32.js";
    modules["cubicBezier.js"] = "/**\n * 本模块提供贝塞尔曲线工具\n * 源码来自B站原生header.js工程,具体来源不明\n * 稍作修改以符合本项目需求\n */\n(function () {\n    try {\n        const NEWTON_ITERATIONS = 4;\n        const NEWTON_MIN_SLOPE = 0.001;\n        const SUBDIVISION_PRECISION = 0.0000001;\n        const SUBDIVISION_MAX_ITERATIONS = 10;\n        const kSplineTableSize = 11;\n        const kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);\n        const float32ArraySupported = typeof Float32Array === 'function';\n        function A(aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1; }\n        function B(aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1; }\n        function C(aA1) { return 3.0 * aA1; }\n        // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.\n        function calcBezier(aT, aA1, aA2) { return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT; }\n        // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.\n        function getSlope(aT, aA1, aA2) { return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1); }\n        function binarySubdivide(aX, aA, aB, mX1, mX2) {\n            let currentX, currentT, i = 0;\n            do {\n                currentT = aA + (aB - aA) / 2.0;\n                currentX = calcBezier(currentT, mX1, mX2) - aX;\n                if (currentX > 0.0) {\n                    aB = currentT;\n                }\n                else {\n                    aA = currentT;\n                }\n            } while (Math.abs(currentX) > SUBDIVISION_PRECISION && ++i < SUBDIVISION_MAX_ITERATIONS);\n            return currentT;\n        }\n        function newtonRaphsonIterate(aX, aGuessT, mX1, mX2) {\n            for (let i = 0; i < NEWTON_ITERATIONS; ++i) {\n                const currentSlope = getSlope(aGuessT, mX1, mX2);\n                if (currentSlope === 0.0) {\n                    return aGuessT;\n                }\n                const currentX = calcBezier(aGuessT, mX1, mX2) - aX;\n                aGuessT -= currentX / currentSlope;\n            }\n            return aGuessT;\n        }\n        function LinearEasing(x) {\n            return x;\n        }\n        API.bezier = function (mX1, mY1, mX2, mY2) {\n            if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) {\n                throw new Error('bezier x values must be in [0, 1] range');\n            }\n            if (mX1 === mY1 && mX2 === mY2) {\n                return LinearEasing;\n            }\n            // Precompute samples table\n            const sampleValues = float32ArraySupported ? new Float32Array(kSplineTableSize) : new Array(kSplineTableSize);\n            for (let i = 0; i < kSplineTableSize; ++i) {\n                sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);\n            }\n            function getTForX(aX) {\n                let intervalStart = 0.0;\n                let currentSample = 1;\n                const lastSample = kSplineTableSize - 1;\n                for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {\n                    intervalStart += kSampleStepSize;\n                }\n                --currentSample;\n                // Interpolate to provide an initial guess for t\n                const dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]);\n                const guessForT = intervalStart + dist * kSampleStepSize;\n                const initialSlope = getSlope(guessForT, mX1, mX2);\n                if (initialSlope >= NEWTON_MIN_SLOPE) {\n                    return newtonRaphsonIterate(aX, guessForT, mX1, mX2);\n                }\n                else if (initialSlope === 0.0) {\n                    return guessForT;\n                }\n                else {\n                    return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2);\n                }\n            }\n            return function BezierEasing(x) {\n                // Because JavaScript number are imprecise, we should guarantee the extremes are right.\n                if (x === 0 || x === 1) {\n                    return x;\n                }\n                return calcBezier(getTForX(x), mY1, mY2);\n            };\n        };\n    }\n    catch (e) {\n        toast.error(\"cubicBezier.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/extensions/cubicBezier.js";
    modules["md5.js"] = "/**\n * 本模块提供md5加密工具,是将`js-md5`修改为符合本项目模块规范的版本\n * 感谢开源项目`js-md5`,源项目信息如下\n * @see js-md5 {@link https://github.com/emn178/js-md5}\n * @license MIT\n */\n(function () {\n    try {\n        const ERROR = 'input is invalid type';\n        const ARRAY_BUFFER = true;\n        const HEX_CHARS = '0123456789abcdef'.split('');\n        const EXTRA = [128, 32768, 8388608, -2147483648];\n        const SHIFT = [0, 8, 16, 24];\n        const OUTPUT_TYPES = ['hex', 'array', 'digest', 'buffer', 'arrayBuffer', 'base64'];\n        const BASE64_ENCODE_CHAR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');\n        let buffer = new ArrayBuffer(68), blocks = new Uint32Array(buffer), buffer8 = new Uint8Array(buffer);\n        let createOutputMethod = function (outputType) {\n            return function (message) {\n                return new Md5(true).update(message)[outputType]();\n            };\n        };\n        let createMethod = function () {\n            let method = createOutputMethod('hex');\n            method.create = function () {\n                return new Md5();\n            };\n            method.update = function (message) {\n                return method.create().update(message);\n            };\n            for (let i = 0; i < OUTPUT_TYPES.length; ++i) {\n                let type = OUTPUT_TYPES[i];\n                method[type] = createOutputMethod(type);\n            }\n            return method;\n        };\n        class Md5 {\n            constructor(sharedMemory) {\n                this.buffer8 = new Uint8Array();\n                this.h0 = 0;\n                this.h1 = 0;\n                this.h2 = 0;\n                this.h3 = 0;\n                this.start = 0;\n                this.bytes = 0;\n                this.hBytes = 0;\n                this.finalized = false;\n                this.hashed = false;\n                this.first = true;\n                this.lastByteIndex = 0;\n                if (sharedMemory) {\n                    blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] =\n                        blocks[4] = blocks[5] = blocks[6] = blocks[7] =\n                            blocks[8] = blocks[9] = blocks[10] = blocks[11] =\n                                blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;\n                    this.blocks = blocks;\n                    this.buffer8 = buffer8;\n                }\n                else {\n                    if (ARRAY_BUFFER) {\n                        let buffer = new ArrayBuffer(68);\n                        this.buffer8 = new Uint8Array(buffer);\n                        this.blocks = new Uint32Array(buffer);\n                    }\n                    else {\n                        this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n                    }\n                }\n                this.toString = this.hex;\n                this.array = this.digest;\n                this.buffer = this.arrayBuffer;\n            }\n            update(message) {\n                if (this.finalized) {\n                    return;\n                }\n                message = typeof message === 'number' ? message + '' : message;\n                let notString, type = typeof message;\n                if (type !== 'string') {\n                    if (type === 'object') {\n                        if (message === null) {\n                            throw ERROR;\n                        }\n                        else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) {\n                            message = new Uint8Array(message);\n                        }\n                        else if (!Array.isArray(message)) {\n                            if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) {\n                                throw ERROR;\n                            }\n                        }\n                    }\n                    else {\n                        throw ERROR;\n                    }\n                    notString = true;\n                }\n                let code, index = 0, i, length = message.length, blocks = this.blocks;\n                let buffer8 = this.buffer8;\n                while (index < length) {\n                    if (this.hashed) {\n                        this.hashed = false;\n                        blocks[0] = blocks[16];\n                        blocks[16] = blocks[1] = blocks[2] = blocks[3] =\n                            blocks[4] = blocks[5] = blocks[6] = blocks[7] =\n                                blocks[8] = blocks[9] = blocks[10] = blocks[11] =\n                                    blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;\n                    }\n                    if (notString) {\n                        if (ARRAY_BUFFER) {\n                            for (i = this.start; index < length && i < 64; ++index) {\n                                buffer8[i++] = message[index];\n                            }\n                        }\n                        else {\n                            for (i = this.start; index < length && i < 64; ++index) {\n                                blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];\n                            }\n                        }\n                    }\n                    else {\n                        if (ARRAY_BUFFER) {\n                            for (i = this.start; index < length && i < 64; ++index) {\n                                code = message.charCodeAt(index);\n                                if (code < 0x80) {\n                                    buffer8[i++] = code;\n                                }\n                                else if (code < 0x800) {\n                                    buffer8[i++] = 0xc0 | (code >> 6);\n                                    buffer8[i++] = 0x80 | (code & 0x3f);\n                                }\n                                else if (code < 0xd800 || code >= 0xe000) {\n                                    buffer8[i++] = 0xe0 | (code >> 12);\n                                    buffer8[i++] = 0x80 | ((code >> 6) & 0x3f);\n                                    buffer8[i++] = 0x80 | (code & 0x3f);\n                                }\n                                else {\n                                    code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));\n                                    buffer8[i++] = 0xf0 | (code >> 18);\n                                    buffer8[i++] = 0x80 | ((code >> 12) & 0x3f);\n                                    buffer8[i++] = 0x80 | ((code >> 6) & 0x3f);\n                                    buffer8[i++] = 0x80 | (code & 0x3f);\n                                }\n                            }\n                        }\n                        else {\n                            for (i = this.start; index < length && i < 64; ++index) {\n                                code = message.charCodeAt(index);\n                                if (code < 0x80) {\n                                    blocks[i >> 2] |= code << SHIFT[i++ & 3];\n                                }\n                                else if (code < 0x800) {\n                                    blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];\n                                    blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];\n                                }\n                                else if (code < 0xd800 || code >= 0xe000) {\n                                    blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];\n                                    blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];\n                                    blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];\n                                }\n                                else {\n                                    code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));\n                                    blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];\n                                    blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];\n                                    blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];\n                                    blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];\n                                }\n                            }\n                        }\n                    }\n                    this.lastByteIndex = i;\n                    this.bytes += i - this.start;\n                    if (i >= 64) {\n                        this.start = i - 64;\n                        this.hash();\n                        this.hashed = true;\n                    }\n                    else {\n                        this.start = i;\n                    }\n                }\n                if (this.bytes > 4294967295) {\n                    this.hBytes += this.bytes / 4294967296 << 0;\n                    this.bytes = this.bytes % 4294967296;\n                }\n                return this;\n            }\n            finalize() {\n                if (this.finalized) {\n                    return;\n                }\n                this.finalized = true;\n                let blocks = this.blocks, i = this.lastByteIndex;\n                blocks[i >> 2] |= EXTRA[i & 3];\n                if (i >= 56) {\n                    if (!this.hashed) {\n                        this.hash();\n                    }\n                    blocks[0] = blocks[16];\n                    blocks[16] = blocks[1] = blocks[2] = blocks[3] =\n                        blocks[4] = blocks[5] = blocks[6] = blocks[7] =\n                            blocks[8] = blocks[9] = blocks[10] = blocks[11] =\n                                blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;\n                }\n                blocks[14] = this.bytes << 3;\n                blocks[15] = this.hBytes << 3 | this.bytes >>> 29;\n                this.hash();\n            }\n            hash() {\n                let a, b, c, d, bc, da, blocks = this.blocks;\n                if (this.first) {\n                    a = blocks[0] - 680876937;\n                    a = (a << 7 | a >>> 25) - 271733879 << 0;\n                    d = (-1732584194 ^ a & 2004318071) + blocks[1] - 117830708;\n                    d = (d << 12 | d >>> 20) + a << 0;\n                    c = (-271733879 ^ (d & (a ^ -271733879))) + blocks[2] - 1126478375;\n                    c = (c << 17 | c >>> 15) + d << 0;\n                    b = (a ^ (c & (d ^ a))) + blocks[3] - 1316259209;\n                    b = (b << 22 | b >>> 10) + c << 0;\n                }\n                else {\n                    a = this.h0;\n                    b = this.h1;\n                    c = this.h2;\n                    d = this.h3;\n                    a += (d ^ (b & (c ^ d))) + blocks[0] - 680876936;\n                    a = (a << 7 | a >>> 25) + b << 0;\n                    d += (c ^ (a & (b ^ c))) + blocks[1] - 389564586;\n                    d = (d << 12 | d >>> 20) + a << 0;\n                    c += (b ^ (d & (a ^ b))) + blocks[2] + 606105819;\n                    c = (c << 17 | c >>> 15) + d << 0;\n                    b += (a ^ (c & (d ^ a))) + blocks[3] - 1044525330;\n                    b = (b << 22 | b >>> 10) + c << 0;\n                }\n                a += (d ^ (b & (c ^ d))) + blocks[4] - 176418897;\n                a = (a << 7 | a >>> 25) + b << 0;\n                d += (c ^ (a & (b ^ c))) + blocks[5] + 1200080426;\n                d = (d << 12 | d >>> 20) + a << 0;\n                c += (b ^ (d & (a ^ b))) + blocks[6] - 1473231341;\n                c = (c << 17 | c >>> 15) + d << 0;\n                b += (a ^ (c & (d ^ a))) + blocks[7] - 45705983;\n                b = (b << 22 | b >>> 10) + c << 0;\n                a += (d ^ (b & (c ^ d))) + blocks[8] + 1770035416;\n                a = (a << 7 | a >>> 25) + b << 0;\n                d += (c ^ (a & (b ^ c))) + blocks[9] - 1958414417;\n                d = (d << 12 | d >>> 20) + a << 0;\n                c += (b ^ (d & (a ^ b))) + blocks[10] - 42063;\n                c = (c << 17 | c >>> 15) + d << 0;\n                b += (a ^ (c & (d ^ a))) + blocks[11] - 1990404162;\n                b = (b << 22 | b >>> 10) + c << 0;\n                a += (d ^ (b & (c ^ d))) + blocks[12] + 1804603682;\n                a = (a << 7 | a >>> 25) + b << 0;\n                d += (c ^ (a & (b ^ c))) + blocks[13] - 40341101;\n                d = (d << 12 | d >>> 20) + a << 0;\n                c += (b ^ (d & (a ^ b))) + blocks[14] - 1502002290;\n                c = (c << 17 | c >>> 15) + d << 0;\n                b += (a ^ (c & (d ^ a))) + blocks[15] + 1236535329;\n                b = (b << 22 | b >>> 10) + c << 0;\n                a += (c ^ (d & (b ^ c))) + blocks[1] - 165796510;\n                a = (a << 5 | a >>> 27) + b << 0;\n                d += (b ^ (c & (a ^ b))) + blocks[6] - 1069501632;\n                d = (d << 9 | d >>> 23) + a << 0;\n                c += (a ^ (b & (d ^ a))) + blocks[11] + 643717713;\n                c = (c << 14 | c >>> 18) + d << 0;\n                b += (d ^ (a & (c ^ d))) + blocks[0] - 373897302;\n                b = (b << 20 | b >>> 12) + c << 0;\n                a += (c ^ (d & (b ^ c))) + blocks[5] - 701558691;\n                a = (a << 5 | a >>> 27) + b << 0;\n                d += (b ^ (c & (a ^ b))) + blocks[10] + 38016083;\n                d = (d << 9 | d >>> 23) + a << 0;\n                c += (a ^ (b & (d ^ a))) + blocks[15] - 660478335;\n                c = (c << 14 | c >>> 18) + d << 0;\n                b += (d ^ (a & (c ^ d))) + blocks[4] - 405537848;\n                b = (b << 20 | b >>> 12) + c << 0;\n                a += (c ^ (d & (b ^ c))) + blocks[9] + 568446438;\n                a = (a << 5 | a >>> 27) + b << 0;\n                d += (b ^ (c & (a ^ b))) + blocks[14] - 1019803690;\n                d = (d << 9 | d >>> 23) + a << 0;\n                c += (a ^ (b & (d ^ a))) + blocks[3] - 187363961;\n                c = (c << 14 | c >>> 18) + d << 0;\n                b += (d ^ (a & (c ^ d))) + blocks[8] + 1163531501;\n                b = (b << 20 | b >>> 12) + c << 0;\n                a += (c ^ (d & (b ^ c))) + blocks[13] - 1444681467;\n                a = (a << 5 | a >>> 27) + b << 0;\n                d += (b ^ (c & (a ^ b))) + blocks[2] - 51403784;\n                d = (d << 9 | d >>> 23) + a << 0;\n                c += (a ^ (b & (d ^ a))) + blocks[7] + 1735328473;\n                c = (c << 14 | c >>> 18) + d << 0;\n                b += (d ^ (a & (c ^ d))) + blocks[12] - 1926607734;\n                b = (b << 20 | b >>> 12) + c << 0;\n                bc = b ^ c;\n                a += (bc ^ d) + blocks[5] - 378558;\n                a = (a << 4 | a >>> 28) + b << 0;\n                d += (bc ^ a) + blocks[8] - 2022574463;\n                d = (d << 11 | d >>> 21) + a << 0;\n                da = d ^ a;\n                c += (da ^ b) + blocks[11] + 1839030562;\n                c = (c << 16 | c >>> 16) + d << 0;\n                b += (da ^ c) + blocks[14] - 35309556;\n                b = (b << 23 | b >>> 9) + c << 0;\n                bc = b ^ c;\n                a += (bc ^ d) + blocks[1] - 1530992060;\n                a = (a << 4 | a >>> 28) + b << 0;\n                d += (bc ^ a) + blocks[4] + 1272893353;\n                d = (d << 11 | d >>> 21) + a << 0;\n                da = d ^ a;\n                c += (da ^ b) + blocks[7] - 155497632;\n                c = (c << 16 | c >>> 16) + d << 0;\n                b += (da ^ c) + blocks[10] - 1094730640;\n                b = (b << 23 | b >>> 9) + c << 0;\n                bc = b ^ c;\n                a += (bc ^ d) + blocks[13] + 681279174;\n                a = (a << 4 | a >>> 28) + b << 0;\n                d += (bc ^ a) + blocks[0] - 358537222;\n                d = (d << 11 | d >>> 21) + a << 0;\n                da = d ^ a;\n                c += (da ^ b) + blocks[3] - 722521979;\n                c = (c << 16 | c >>> 16) + d << 0;\n                b += (da ^ c) + blocks[6] + 76029189;\n                b = (b << 23 | b >>> 9) + c << 0;\n                bc = b ^ c;\n                a += (bc ^ d) + blocks[9] - 640364487;\n                a = (a << 4 | a >>> 28) + b << 0;\n                d += (bc ^ a) + blocks[12] - 421815835;\n                d = (d << 11 | d >>> 21) + a << 0;\n                da = d ^ a;\n                c += (da ^ b) + blocks[15] + 530742520;\n                c = (c << 16 | c >>> 16) + d << 0;\n                b += (da ^ c) + blocks[2] - 995338651;\n                b = (b << 23 | b >>> 9) + c << 0;\n                a += (c ^ (b | ~d)) + blocks[0] - 198630844;\n                a = (a << 6 | a >>> 26) + b << 0;\n                d += (b ^ (a | ~c)) + blocks[7] + 1126891415;\n                d = (d << 10 | d >>> 22) + a << 0;\n                c += (a ^ (d | ~b)) + blocks[14] - 1416354905;\n                c = (c << 15 | c >>> 17) + d << 0;\n                b += (d ^ (c | ~a)) + blocks[5] - 57434055;\n                b = (b << 21 | b >>> 11) + c << 0;\n                a += (c ^ (b | ~d)) + blocks[12] + 1700485571;\n                a = (a << 6 | a >>> 26) + b << 0;\n                d += (b ^ (a | ~c)) + blocks[3] - 1894986606;\n                d = (d << 10 | d >>> 22) + a << 0;\n                c += (a ^ (d | ~b)) + blocks[10] - 1051523;\n                c = (c << 15 | c >>> 17) + d << 0;\n                b += (d ^ (c | ~a)) + blocks[1] - 2054922799;\n                b = (b << 21 | b >>> 11) + c << 0;\n                a += (c ^ (b | ~d)) + blocks[8] + 1873313359;\n                a = (a << 6 | a >>> 26) + b << 0;\n                d += (b ^ (a | ~c)) + blocks[15] - 30611744;\n                d = (d << 10 | d >>> 22) + a << 0;\n                c += (a ^ (d | ~b)) + blocks[6] - 1560198380;\n                c = (c << 15 | c >>> 17) + d << 0;\n                b += (d ^ (c | ~a)) + blocks[13] + 1309151649;\n                b = (b << 21 | b >>> 11) + c << 0;\n                a += (c ^ (b | ~d)) + blocks[4] - 145523070;\n                a = (a << 6 | a >>> 26) + b << 0;\n                d += (b ^ (a | ~c)) + blocks[11] - 1120210379;\n                d = (d << 10 | d >>> 22) + a << 0;\n                c += (a ^ (d | ~b)) + blocks[2] + 718787259;\n                c = (c << 15 | c >>> 17) + d << 0;\n                b += (d ^ (c | ~a)) + blocks[9] - 343485551;\n                b = (b << 21 | b >>> 11) + c << 0;\n                if (this.first) {\n                    this.h0 = a + 1732584193 << 0;\n                    this.h1 = b - 271733879 << 0;\n                    this.h2 = c - 1732584194 << 0;\n                    this.h3 = d + 271733878 << 0;\n                    this.first = false;\n                }\n                else {\n                    this.h0 = this.h0 + a << 0;\n                    this.h1 = this.h1 + b << 0;\n                    this.h2 = this.h2 + c << 0;\n                    this.h3 = this.h3 + d << 0;\n                }\n            }\n            hex() {\n                this.finalize();\n                let h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3;\n                return HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] +\n                    HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] +\n                    HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] +\n                    HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] +\n                    HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] +\n                    HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] +\n                    HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] +\n                    HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] +\n                    HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] +\n                    HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] +\n                    HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] +\n                    HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] +\n                    HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] +\n                    HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] +\n                    HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] +\n                    HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F];\n            }\n            digest() {\n                this.finalize();\n                let h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3;\n                return [\n                    h0 & 0xFF, (h0 >> 8) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 24) & 0xFF,\n                    h1 & 0xFF, (h1 >> 8) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 24) & 0xFF,\n                    h2 & 0xFF, (h2 >> 8) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 24) & 0xFF,\n                    h3 & 0xFF, (h3 >> 8) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 24) & 0xFF\n                ];\n            }\n            arrayBuffer() {\n                this.finalize();\n                let buffer = new ArrayBuffer(16);\n                let blocks = new Uint32Array(buffer);\n                blocks[0] = this.h0;\n                blocks[1] = this.h1;\n                blocks[2] = this.h2;\n                blocks[3] = this.h3;\n                return buffer;\n            }\n            base64() {\n                let i, v1, v2, v3, base64Str = '', bytes = this.array();\n                for (i = 0; i < 15;) {\n                    v1 = bytes[i++];\n                    v2 = bytes[i++];\n                    v3 = bytes[i++];\n                    base64Str += BASE64_ENCODE_CHAR[v1 >>> 2] +\n                        BASE64_ENCODE_CHAR[(v1 << 4 | v2 >>> 4) & 63] +\n                        BASE64_ENCODE_CHAR[(v2 << 2 | v3 >>> 6) & 63] +\n                        BASE64_ENCODE_CHAR[v3 & 63];\n                }\n                v1 = bytes[i];\n                base64Str += BASE64_ENCODE_CHAR[v1 >>> 2] +\n                    BASE64_ENCODE_CHAR[(v1 << 4) & 63] +\n                    '==';\n                return base64Str;\n            }\n        }\n        API.md5 = createMethod();\n    }\n    catch (e) {\n        toast.error(\"md5.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/extensions/md5.js";
    modules["sign.js"] = "/**\n * 本模块提供B站URL签名工具\n */\n(function () {\n    try {\n        /**\n         * appkey and salt\n         * 注释后是带掩码版 appkey\n         * 强烈建议还是专事专用\n         */\n        const keySecret = [\n            \"rbMCKn@KuamXWlPMoJGsKcbiJKUfkPF_8dABscJntvqhRSETg\",\n            \"/a_206b`_.61.bca6117.175bcdadc41850c010c..././1``\",\n            \"157bdd`6/bc73632.bcd660baa03a.43841211032b5c4`6b/\",\n            \"351a7a6b/.b`d77da1cdccc25_13bc0a81a6d63.7ad13`c50\",\n            \"4_/54d`3_4_73..2c42`d4.a3__31b358d706d`._7a.3_b5.\",\n            \"12a.7c4b76c.a`12bb4`2b2b275c667c85b6d`c_c`0d5.051\",\n            \"bb16d652`04.7/121d3474b_2.c12`7386`0/bdd6ca0c7.22\",\n            \"244_530/7/.ab`7.//22a15572502b_08c21./_.`3164`c36\",\n            \"16_d52_d/d22_2c0a.6573355/b`./bd8a`bc6114a30_4.`d\",\n            \"c02ba/d6.33d05cb/5d34.7d_23_`_2785`c60.a`.4343726\",\n            \"2aa2`.1_`_1.73`.70.67d.bc671c16382a3d`71a4.bcb3c7\",\n            \"40/171b046c/bcc0a603ac620`372ba_8d706d`._7a.3_b5.\",\n            \"c4_a.7562_15`_a416a/63/c2cbcb`308a/`//41b30376.b5\" // 7d08...1b1c\n        ];\n        class Sign {\n            /**\n             * 签名URL\n             * @param url 原URL\n             * @param obj 添加到URL上的查询参数对象,可选\n             * @param id appkey在`keySecret`中的索引\n             * @returns 签名后的URL\n             */\n            static sign(url, obj = {}, id = 0) {\n                let table = {};\n                this.keySecret = this.decode(id);\n                obj = { ...API.urlObj(url), ...obj };\n                url = url.split(\"#\")[0].split(\"?\")[0];\n                delete obj.sign;\n                obj.appkey = this.keySecret[0];\n                Object.keys(obj).sort().map(key => { table[key] = obj[key]; });\n                table.sign = id === 3 && table.api ? (API.md5(API.objUrl(\"\", { api: decodeURIComponent(table.api) }) + this.keySecret[1])) : (API.md5(API.objUrl(\"\", table) + this.keySecret[1]));\n                return API.objUrl(url, table);\n            }\n            /**\n             * 提取appkey和盐\n             * @param id appkey在`keySecret`中的索引\n             * @returns [appkey, sort]\n             */\n            static decode(id) {\n                if (typeof id === \"number\") {\n                    id = id < keySecret.length ? id : 0;\n                    return keySecret[id].split(\"\").reverse().reduce((s, d) => {\n                        s = s + String.fromCharCode(d.charCodeAt(0) + 2);\n                        return s;\n                    }, '').split(\":\");\n                }\n                else {\n                    return [id, this.list()[id]];\n                }\n            }\n            /**\n             * 生成`keySecret`池\n             * @param key appkey\n             * @param secret appkey对应的盐\n             * @returns 混淆后的字符串\n             */\n            static encode(key, secret) {\n                return (key + \":\" + secret).split(\"\").reverse().reduce((s, d) => {\n                    s = s + String.fromCharCode(d.charCodeAt(0) - 2);\n                    return s;\n                }, \"\");\n            }\n            /**\n             * 输出`keySecret`池对象\n             * @returns `keySecret`池对象\n             */\n            static list() {\n                return keySecret.reduce((s, d, i) => {\n                    let keySecret = this.decode(i);\n                    s[keySecret[0]] = keySecret[1];\n                    return s;\n                }, {});\n            }\n        }\n        const urlsign = (url, obj = {}, id = 0) => Sign.sign(url, obj, id);\n        urlsign.getKeyById = (id) => Sign.decode(id);\n        urlsign.encode = (key, secret) => Sign.encode(key, secret);\n        urlsign.list = () => Sign.list();\n        API.urlsign = urlsign;\n    }\n    catch (e) {\n        toast.error(\"sign.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/extensions/sign.js";
    modules["Node.js"] = "/**\n * 本模块负责实现原生脚本拦截模块\n * 这里指的原生脚本是那些非直接写入原生HTML,而是后续由JavaScript添加进DOM的脚本\n * 本模块导入优先级极高\n */\n(function () {\n    try {\n        class NodeHook {\n            constructor() {\n                this.jsonphook = (url, callback) => NodeHook.jsonp.push([url, callback]);\n                this.removeJsonphook = (id) => NodeHook.jsonp.splice(id - 1, 1);\n                this.appendChild();\n                this.insertBefore();\n            }\n            intercept(rule, replaceURL) {\n                NodeHook.rules.push([rule, replaceURL]);\n            }\n            appendChild() {\n                Node.prototype.appendChild = function (newChild) {\n                    newChild.nodeName == 'SCRIPT' && newChild.src && (NodeHook.rules.forEach(d => {\n                        d[0].every(d => newChild.src.includes(d)) && (d[1] ?\n                            (newChild.src = d[1]) :\n                            newChild.removeAttribute(\"src\"));\n                    }), NodeHook.jsonp.forEach(d => {\n                        d[0].every(d => newChild.src.includes(d)) && d[1](new Proxy(new Object(), {\n                            set: (t, p, v) => {\n                                p == \"url\" && (newChild.src = v);\n                                return true;\n                            },\n                            get: (t, p) => {\n                                return p == \"url\" ? newChild.src : undefined;\n                            }\n                        }));\n                    }));\n                    return NodeHook.appendChild.call(this, newChild);\n                };\n            }\n            insertBefore() {\n                Node.prototype.insertBefore = function (newChild, refChild) {\n                    newChild.nodeName == 'SCRIPT' && newChild.src && (NodeHook.rules.forEach(d => {\n                        d[0].every(d => newChild.src.includes(d)) && (d[1] ?\n                            (newChild.src = d[1]) :\n                            newChild.removeAttribute(\"src\"));\n                    }), NodeHook.jsonp.forEach(d => {\n                        d[0].every(d => newChild.src.includes(d)) && d[1](new Proxy(new Object(), {\n                            set: (t, p, v) => {\n                                p == \"url\" && (newChild.src = v);\n                                return true;\n                            },\n                            get: (t, p) => {\n                                return p == \"url\" ? newChild.src : undefined;\n                            }\n                        }));\n                    }));\n                    return NodeHook.insertBefore.call(this, newChild, refChild);\n                };\n            }\n        }\n        NodeHook.appendChild = Node.prototype.appendChild;\n        NodeHook.insertBefore = Node.prototype.insertBefore;\n        NodeHook.rules = [];\n        NodeHook.jsonp = [];\n        const nodeHook = new NodeHook();\n        API.scriptIntercept = (rule, replaceURL) => nodeHook.intercept(rule, replaceURL);\n        API.jsonphook = (url, callback) => nodeHook.jsonphook(url, callback);\n        API.removeJsonphook = (id) => nodeHook.removeJsonphook(id);\n    }\n    catch (e) {\n        toast.error(\"Node.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/hook/Node.js";
    modules["open.js"] = "/**\n * 本模块负责提供`XMLHttpRequest`的hook工具\n * 拦截`open`参数组并传入`XMLHttpRequest`对象本身给回调函数\n */\n(function () {\n    try {\n        const rules = [];\n        const open = XMLHttpRequest.prototype.open;\n        API.xhrhook = (url, callback) => rules.push([url, callback]);\n        API.removeXhrhook = (id) => rules.splice(id - 1, 1);\n        XMLHttpRequest.prototype.open = function (...rest) {\n            let args = [...rest];\n            args[1] && rules.forEach(d => {\n                d[0].every(d => args[1].includes(d)) && d[1].call(this, args);\n            });\n            return open.call(this, ...args);\n        };\n    }\n    catch (e) {\n        toast.error(\"open.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/hook/open.js";
    modules["webSocket.js"] = "/**\n * 本模块hook了WebSocket以修复旧版播放器的实时弹幕\n * 告知:本模块由js强行any为ts版本,可能需要进一步优化\n */\n(function () {\n    try {\n        let decoder = new TextDecoder();\n        let encoder = new TextEncoder();\n        let liveChatOld; // 对旧播放器建立的ws对象的引用\n        let liveChat;\n        // 为了获取ws对象的引用,hook WebSocket.send\n        let wsHookRunOnce = true;\n        const wssend = WebSocket.prototype.send;\n        WebSocket.prototype.send = function (...arg) {\n            if (wsHookRunOnce && this.url == 'wss://broadcast.chat.bilibili.com:4095/sub') {\n                liveChatOld = this;\n                // 切p和掉线之后需要重新启动hook,获得新的引用\n                let onclose = liveChatOld.onclose;\n                liveChatOld.onclose = function () {\n                    wsHookRunOnce = true;\n                    clearTimeout(liveChat.heatTimer);\n                    liveChat.close();\n                    onclose.call(this);\n                };\n                // 从bilibiliPlayer.js > b.prototype.xx复制过来\n                // 编码一个数据包\n                // body[Object] : 要发送的信息\n                // option[Number] : 数据包对应的行为\n                //                  =5 一条弹幕数据\n                //                  =7 首个数据包,建立与服务器的连接\n                // return[Buffer] : 包装好的数据\n                liveChatOld.convertToArrayBuffer = function (body, option) {\n                    let header = [{ \"name\": \"Header Length\", \"key\": \"headerLen\", \"qg\": 2, \"offset\": 4, \"value\": 16 }, { \"name\": \"Protocol Version\", \"key\": \"ver\", \"qg\": 2, \"offset\": 6, \"value\": 1 }, { \"name\": \"Operation\", \"key\": \"op\", \"qg\": 4, \"offset\": 8, \"value\": option }, { \"name\": \"Sequence Id\", \"key\": \"seq\", \"qg\": 4, \"offset\": 12, \"value\": 1 }];\n                    let headerBuf = new ArrayBuffer(16);\n                    let viewer = new DataView(headerBuf, 0);\n                    let bodyBuf = encoder.encode(JSON.stringify(body));\n                    viewer.setInt32(0, 16 + bodyBuf.byteLength);\n                    header.forEach(function (b) {\n                        4 === b.qg ? viewer.setInt32(b.offset, b.value) : 2 === b.qg && viewer.setInt16(b.offset, b.value);\n                    });\n                    return mergeArrayBuffer(headerBuf, bodyBuf);\n                };\n                wsHookRunOnce = false;\n                initLiveChat();\n            }\n            wssend.call(this, ...arg);\n        };\n        // 原函数位于bilibiliPlayer.js > c.a.eK 和 jsc-player > Dl.mergeArrayBuffer\n        // 连接两个buffer\n        function mergeArrayBuffer(headerBuf, bodyBuf) {\n            headerBuf = new Uint8Array(headerBuf);\n            bodyBuf = new Uint8Array(bodyBuf);\n            var d = new Uint8Array(headerBuf.byteLength + bodyBuf.byteLength);\n            d.set(headerBuf, 0);\n            d.set(bodyBuf, headerBuf.byteLength);\n            return d.buffer;\n        }\n        function initLiveChat() {\n            // 数据包对应的Operation常量表\n            let Pl = { \"WS_OP_HEARTBEAT\": 2, \"WS_OP_HEARTBEAT_REPLY\": 3, \"WS_OP_DATA\": 1000, \"WS_OP_BATCH_DATA\": 9, \"WS_OP_DISCONNECT_REPLY\": 6, \"WS_OP_USER_AUTHENTICATION\": 7, \"WS_OP_CONNECT_SUCCESS\": 8, \"WS_OP_CHANGEROOM\": 12, \"WS_OP_CHANGEROOM_REPLY\": 13, \"WS_OP_REGISTER\": 14, \"WS_OP_REGISTER_REPLY\": 15, \"WS_OP_UNREGISTER\": 16, \"WS_OP_UNREGISTER_REPLY\": 17, \"WS_OP_OGVCMD_REPLY\": 1015, \"WS_PACKAGE_HEADER_TOTAL_LENGTH\": 18, \"WS_PACKAGE_OFFSET\": 0, \"WS_HEADER_OFFSET\": 4, \"WS_VERSION_OFFSET\": 6, \"WS_OPERATION_OFFSET\": 8, \"WS_SEQUENCE_OFFSET\": 12, \"WS_COMPRESS_OFFSET\": 16, \"WS_CONTENTTYPE_OFFSET\": 17, \"WS_BODY_PROTOCOL_VERSION\": 1, \"WS_HEADER_DEFAULT_VERSION\": 1, \"WS_HEADER_DEFAULT_OPERATION\": 1, \"ws_header_default_sequence\": 1, \"WS_HEADER_DEFAULT_COMPRESS\": 0, \"WS_HEADER_DEFAULT_CONTENTTYPE\": 0 };\n            // 请求头的参数表\n            let wsBinaryHeaderList = [{ \"name\": \"Header Length\", \"key\": \"headerLen\", \"bytes\": 2, \"offset\": 4, \"value\": 18 }, { \"name\": \"Protocol Version\", \"key\": \"ver\", \"bytes\": 2, \"offset\": 6, \"value\": 1 }, { \"name\": \"Operation\", \"key\": \"op\", \"bytes\": 4, \"offset\": 8, \"value\": 7 }, { \"name\": \"Sequence Id\", \"key\": \"seq\", \"bytes\": 4, \"offset\": 12, \"value\": 2 }, { \"name\": \"Compress\", \"key\": \"compress\", \"bytes\": 1, \"offset\": 16, \"value\": 0 }, { \"name\": \"ContentType\", \"key\": \"contentType\", \"bytes\": 1, \"offset\": 17, \"value\": 0 }];\n            liveChat = new WebSocket('wss://broadcast.chat.bilibili.com:7823/sub');\n            liveChat.binaryType = \"arraybuffer\";\n            liveChat.heatTimer = -1;\n            // 每30秒一个心跳包\n            liveChat.heartBeat = function () {\n                var i = this;\n                clearTimeout(this.heatTimer);\n                var e = this.convertToArrayBuffer({}, Pl.WS_OP_HEARTBEAT);\n                this.send(e);\n                this.heatTimer = window.setTimeout((function () {\n                    i.heartBeat();\n                }), 1e3 * 30);\n            };\n            liveChat.onopen = function () {\n                let body = {\n                    \"room_id\": \"video://\" + API.aid + \"/\" + API.cid,\n                    \"platform\": \"web\",\n                    \"accepts\": [1000, 1015]\n                };\n                return this.send(this.convertToArrayBuffer(body, 7));\n            };\n            liveChat.onmessage = function (i) {\n                try {\n                    var t = this.convertToObject(i.data);\n                    if (t) {\n                        switch (t.op) {\n                            case Pl.WS_OP_HEARTBEAT_REPLY:\n                                // 接收到心跳包后,服务器响应当前在线人数的数据\n                                // 旧播放器连接的4095端口,虽然不再下发实时弹幕,但依然照常响应在线人数\n                                // 所以暂时不用替换成新版\n                                // this.onHeartBeatReply(t.body);\n                                break;\n                            case Pl.WS_OP_CONNECT_SUCCESS:\n                                this.heartBeat();\n                                break;\n                            // 旧播放器只能处理(连接成功,心跳响应,实时弹幕)三种响应信息\n                            // 新播放器新增的指令和功能就不管了\n                            case Pl.WS_OP_CHANGEROOM_REPLY:\n                                //0 === Number(t.body.code) && this.options.onChangeRoomReply({ data : t && t.body });\n                                break;\n                            case Pl.WS_OP_REGISTER_REPLY:\n                                //0 === Number(t.body.code) && this.options.onRegisterReply({ data : t && t.body });\n                                break;\n                            case Pl.WS_OP_UNREGISTER_REPLY:\n                                //0 === Number(t.body.code) && this.options.onUnRegisterReply({ data : t && t.body });\n                                break;\n                            case Pl.WS_OP_DATA:\n                            case Pl.WS_OP_BATCH_DATA:\n                                t.body.forEach(function (v) {\n                                    liveChatOld.onmessage({\n                                        data: liveChatOld.convertToArrayBuffer({\n                                            cmd: 'DM',\n                                            info: [v[0], v[1]]\n                                        }, 5)\n                                    });\n                                });\n                                break;\n                            case Pl.WS_OP_OGVCMD_REPLY:\n                                //this.onOgvCmdReply(t);\n                                break;\n                            default:\n                            //this.msgReply(t)\n                        }\n                    }\n                }\n                catch (i) {\n                    console.error(\"WebSocket Error : \", i);\n                }\n                return this;\n            };\n            // jsc-player > i.prototype.convertToArrayBuffer,新版播放器的请求头信息更多,需要18字节\n            // 基本与liveChatOld.convertToArrayBuffer相同\n            liveChat.convertToArrayBuffer = function (body, option) {\n                let headerBuf = new ArrayBuffer(Pl.WS_PACKAGE_HEADER_TOTAL_LENGTH);\n                let viewer = new DataView(headerBuf, Pl.WS_PACKAGE_OFFSET);\n                let bodyBuf = encoder.encode(JSON.stringify(body));\n                viewer.setInt32(Pl.WS_PACKAGE_OFFSET, Pl.WS_PACKAGE_HEADER_TOTAL_LENGTH + bodyBuf.byteLength);\n                wsBinaryHeaderList[2].value = option;\n                wsBinaryHeaderList.forEach((function (i) {\n                    4 === i.bytes ? (viewer.setInt32(i.offset, i.value),\n                        \"seq\" === i.key && ++i.value) : 2 === i.bytes ? viewer.setInt16(i.offset, i.value) : 1 === i.bytes && viewer.setInt8(i.offset, i.value);\n                }));\n                return mergeArrayBuffer(headerBuf, bodyBuf);\n            };\n            // jsc-player > i.prototype.convertToObject\n            // convertToArrayBuffer对应的解码函数\n            liveChat.convertToObject = function (i) {\n                var e = new DataView(i), t = {};\n                t.packetLen = e.getInt32(Pl.WS_PACKAGE_OFFSET);\n                wsBinaryHeaderList.forEach((function (i) {\n                    4 === i.bytes ? t[i.key] = e.getInt32(i.offset) : 2 === i.bytes ? t[i.key] = e.getInt16(i.offset) : 1 === i.bytes && (t[i.key] = e.getInt8(i.offset));\n                }));\n                if (t.op && t.op === Pl.WS_OP_BATCH_DATA) {\n                    t.body = this.parseDanmaku(i, e, Pl.WS_PACKAGE_HEADER_TOTAL_LENGTH, t.packetLen);\n                }\n                else if (t.op && Pl.WS_OP_DATA === t.op) {\n                    t.body = this.parseDanmaku(i, e, Pl.WS_PACKAGE_OFFSET, t.packetLen);\n                }\n                else if (t.op && t.op === Pl.WS_OP_OGVCMD_REPLY) {\n                    t.body = \"\"; // this.parseOgvCmd(i, e, Pl.WS_PACKAGE_OFFSET, t.packetLen);\n                }\n                else if (t.op) {\n                    t.body = [];\n                    for (var a = Pl.WS_PACKAGE_OFFSET, r = t.packetLen, n = \"\", l = \"\"; a < i.byteLength; a += r) {\n                        r = e.getInt32(a);\n                        n = e.getInt16(a + Pl.WS_HEADER_OFFSET);\n                        try {\n                            l = JSON.parse(decoder.decode(i.slice(a + n, a + r)));\n                            t.body = l;\n                        }\n                        catch (e) {\n                            l = decoder.decode(i.slice(a + n, a + r));\n                            console.error(\"decode body error:\", new Uint8Array(i), t);\n                        }\n                    }\n                }\n                return t;\n            };\n            // jsc-player > i.prototype.parseDanmaku\n            liveChat.parseDanmaku = function (i, e, t, a) {\n                for (var r, n = [], l = t; l < i.byteLength; l += a) {\n                    a = e.getInt32(l);\n                    r = e.getInt16(l + Pl.WS_HEADER_OFFSET);\n                    try {\n                        n.push(JSON.parse(decoder.decode(i.slice(l + r, l + a))));\n                    }\n                    catch (e) {\n                        n.push(decoder.decode(i.slice(l + r, l + a)));\n                        console.error(\"decode body error:\", new Uint8Array(i));\n                    }\n                }\n                return n;\n            };\n        }\n    }\n    catch (e) {\n        toast.error(\"webSocket.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/hook/webSocket.js";
    modules["worker.js"] = "/**\n * 本模块hook了Worker以使旧版播放器支持新版proto弹幕\n */\n(function () {\n    try {\n        let workerPostMsg = Worker.prototype.postMessage;\n        let list_so;\n        Worker.prototype.postMessage = function (aMessage, transferList) {\n            if (aMessage.url && aMessage.url.includes(\"list.so\")) {\n                list_so = this;\n                let triggerOnMsg = (danmaku, loadTime, parseTime) => list_so.onmessage({\n                    data: {\n                        code: 0,\n                        danmakuArray: danmaku,\n                        loadTime: loadTime,\n                        parseTime: parseTime,\n                        sendTip: \"\",\n                        state: 0,\n                        textSide: \"\",\n                        total: danmaku.length.toString()\n                    }\n                });\n                let loadDanmaku = (loadTime) => API.getSegDanmaku().then((Segments) => {\n                    // 旧播放器需要得到耗时数据(网络请求,数据处理)\n                    loadTime = new Date() - loadTime;\n                    let parseTime = new Date();\n                    let danmaku = API.danmakuFormat(Segments);\n                    parseTime = new Date() - parseTime;\n                    triggerOnMsg(danmaku, loadTime, parseTime);\n                    API.danmaku = danmaku;\n                });\n                if (XMLHttpRequest.prototype.pakku_send === undefined) {\n                    loadDanmaku(new Date());\n                }\n                else {\n                    // 让pakku.js载入弹幕\n                    let url = \"https://api.bilibili.com/x/v2/dm/web/seg.so?type=1&oid=\" + API.cid + \"&pid=\" + API.aid + \"&segment_index=1\";\n                    xhr({ url: url, responseType: \"arraybuffer\", credentials: true }).then((response) => {\n                        let Segments = API.segDmDecode(response);\n                        // pakku.js处于“休眠中”时,不会修改响应数据,这时的response仅仅是第一个分段的弹幕数据\n                        // 这种情况下需要主动去加载全部的分段(loadDanmaku)\n                        let i = 1;\n                        for (; i < Segments.length; i++) {\n                            // pakku.js处理过的弹幕,在出现时间上按升序排列,可以用这个特征加以区别是否应该载入完整的弹幕\n                            if (Segments[i - 1].progress > Segments[i].progress)\n                                break;\n                        }\n                        if (i != Segments.length)\n                            loadDanmaku(new Date());\n                        else {\n                            triggerOnMsg(API.danmaku = API.danmakuFormat(Segments), \"(pakku.js)\", \"(pakku.js)\");\n                        }\n                    });\n                }\n            }\n            else {\n                workerPostMsg.call(this, aMessage, transferList);\n            }\n        };\n    }\n    catch (e) {\n        toast.error(\"worker.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/hook/worker.js";
    modules["anime.js"] = "/**\n * 本模块负责重写番剧分区主页\n * 本模块未正式启用及完善,待cookies完全失效后再说\n */\n(function () {\n    try {\n        class Anime {\n            constructor() {\n                API.path.name = \"anime\";\n                this.write();\n            }\n            write() {\n                API.rewriteHTML(API.getModule(\"anime.html\"));\n            }\n        }\n        new Anime();\n    }\n    catch (e) {\n        debug.error(\"anime.js\", e);\n        API.importModule(\"vector.js\");\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/anime.js";
    modules["bnj2021.js"] = "/**\n * 本模块负责替换拜年祭2021专题页面使用旧版嵌入播放器\n */\n(function () {\n    API.runWhile(() => window.__INITIAL_STATE__, () => {\n        try {\n            const titles = window.__INITIAL_STATE__.videoSections.reduce((s, d) => {\n                d.episodes.forEach(d => s.push(d));\n                return s;\n            }, []);\n            // 替换播放器节点\n            const node = document.querySelector(\"#bilibili-player\");\n            const iframe = document.createElement('iframe');\n            iframe.src = `https://www.bilibili.com/blackboard/html5player.html?aid=${window.__INITIAL_STATE__.videoInfo.aid}&cid=${window.__INITIAL_STATE__.videoInfo.cid}&enable_ssl=1&crossDomain=1&as_wide=1`;\n            iframe.setAttribute(\"style\", \"width: 906px; height: 556px;border:none;\");\n            iframe.setAttribute(\"id\", \"bofqi\");\n            node.replaceWith(iframe);\n            // 添加时间戳监听\n            const episodes = document.querySelectorAll('.video-episode-card__info-title');\n            episodes.forEach((d, i, e) => {\n                const episode = titles.find(t => t.title == d.innerText);\n                e[i].parentNode.parentNode.onclick = () => {\n                    toast(episode.title, `av${Reflect.get(episode, \"aid\")}`, `UP主:${Reflect.get(episode, \"author\").name}`);\n                    iframe.contentWindow.postMessage({ aid: Reflect.get(episode, \"aid\"), cid: Reflect.get(episode, \"cid\") });\n                };\n            });\n        }\n        catch (e) {\n            toast.error(\"bnj2021.js\", e);\n        }\n    });\n})();\n\n//# sourceURL=API://@bilibili/dist/match/bnj2021.js";
    modules["history.js"] = "/**\n * 本模块负责处理历史记录页面\n */\n(function () {\n    try {\n        config.history && API.xhrhook([\"api.bilibili.com/x/web-interface/history/cursor\", \"business\"], function (args) {\n            let obj = API.urlObj(args[1]), max = obj.max || \"\", view_at = obj.view_at || \"\";\n            args[1] = API.objUrl(\"//api.bilibili.com/x/web-interface/history/cursor\", { max: max, view_at: view_at, type: \"archive\", ps: \"20\" });\n        });\n        config.searchHistory && API.runWhile(() => document.querySelector(\".b-head-search\"), () => { var _a; return (_a = document.querySelector(\".b-head-search\")) === null || _a === void 0 ? void 0 : _a.remove(); });\n    }\n    catch (e) {\n        debug.error(\"history.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/history.js";
    modules["player.js"] = "/**\n * 本模块负责重写旧版嵌入播放器\n */\n(function () {\n    try {\n        API.path.name = \"player\";\n        const obj = API.urlObj(location.href);\n        obj.avid && (Number(obj.avid) ? Reflect.set(window, \"aid\", obj.avid) : Reflect.set(window, \"aid\", API.abv(obj.avid)));\n        !Reflect.has(window, \"aid\") && obj.bvid && Reflect.set(window, \"aid\", API.abv(obj.bvid));\n        obj.cid && Number(obj.cid) && Reflect.set(window, \"cid\", obj.cid);\n        API.restorePlayerSetting(); // 备份还原旧版播放器设置数据\n        API.rewriteHTML(API.getModule(\"player.html\"));\n        API.runWhile(() => document.body, () => {\n            window.addEventListener('message', e => {\n                if (e.data.cid) {\n                    window.__playinfo__ = undefined;\n                    e.data.as_wide = 1;\n                    e.data.dashSymbol = true;\n                    e.data.p = 1;\n                    e.data.pre_ad = \"\";\n                    history.replaceState(undefined, undefined, API.objUrl(\"https://www.bilibili.com/blackboard/html5player.html\", { aid: e.data.aid, cid: e.data.cid }));\n                    window.player = new window.BilibiliPlayer(e.data);\n                }\n            });\n        });\n    }\n    catch (e) {\n        toast.error(\"player.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/player.js";
    modules["ranking.js"] = "/**\n * 本模块负责重写全站排行榜页面\n */\n(function () {\n    try {\n        class Ranking {\n            constructor() {\n                this.refer = document.referrer.split(\"/\");\n                this.obj = { rid: \"0\", day: \"3\", type: \"1\", arc_type: \"0\" };\n                API.path.name = \"ranking\";\n                (this.refer && this.refer[4] && this.refer[4] == \"all\") && Reflect.set(this.obj, \"rid\", this.refer[5]);\n                config.rewriteMethod == \"异步\" ? this.prepareA() : this.prepareB();\n            }\n            prepareA() {\n                xhr({\n                    url: API.objUrl(\"https://api.bilibili.com/x/web-interface/ranking\", this.obj),\n                    responseType: \"json\",\n                    credentials: true\n                }).then(d => { this.write(d); });\n            }\n            prepareB() {\n                let data = xhr({\n                    url: API.objUrl(\"https://api.bilibili.com/x/web-interface/ranking\", this.obj),\n                    async: false,\n                    credentials: true\n                });\n                this.write(data);\n            }\n            write(d) {\n                const data = API.jsonCheck(d);\n                const result = { loading: false, rankRouteParams: { arc_type: 0, day: 3, rankTab: \"all\", rid: Number(this.refer[5]) || 0, season_type: 1 }, showTypes: true, times: [{ name: \"日排行\", value: 1 }, { name: \"三日排行\", value: 3 }, { name: \"周排行\", value: 7 }, { name: \"月排行\", value: 30 }], typeList: [{ name: \"全部投稿\", value: 0 }, { name: \"近期投稿\", value: 1 }] };\n                result.channels = [{ name: \"全站\", tid: 0 }, { name: \"动画\", tid: 1 }, { name: \"国创相关\", tid: 168 }, { name: \"音乐\", tid: 3 }, { name: \"舞蹈\", tid: 129 }, { name: \"游戏\", tid: 4 }, { name: \"知识\", tid: 36 }, { name: \"数码\", tid: 188 }, { name: \"生活\", tid: 160 }, { name: \"美食\", tid: 211 }, { name: \"鬼畜\", tid: 119 }, { name: \"时尚\", tid: 155 }, { name: \"娱乐\", tid: 5 }, { name: \"影视\", tid: 181 }];\n                result.rankList = data.data.list;\n                result.note = data.data.note;\n                window.__INITIAL_STATE__ = result;\n                API.rewriteHTML(API.getModule(\"ranking.html\"));\n                API.addCss(\"@media screen and (min-width: 1400px){.main-inner {width: 1160px !important;}}\");\n            }\n        }\n        new Ranking();\n    }\n    catch (e) {\n        toast.error(\"ranking.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/ranking.js";
    modules["read.js"] = "/**\n * 本模块负责重新旧版专栏页面\n */\n(function () {\n    try {\n        class Read {\n            constructor() {\n                this.bar = [\n                    [0, \"推荐\", \"home\"],\n                    [2, \"动画\", \"douga\"],\n                    [1, \"游戏\", \"game\"],\n                    [28, \"影视\", \"cinephile\"],\n                    [3, \"生活\", \"life\"],\n                    [29, \"兴趣\", \"interest\"],\n                    [16, \"轻小说\", \"lightnovel\"],\n                    [17, \"科技\", \"technology\"],\n                    [41, \"笔记\", \"note\"]\n                ];\n                this.data = \"\";\n                this.temp = \"\";\n                API.path.name = \"read\";\n                config.rewriteMethod == \"异步\" ? this.prepareA() : this.prepareB();\n            }\n            prepareA() {\n                xhr({ url: location.href, credentials: true }).then(d => { this.build(d); });\n            }\n            prepareB() {\n                let data = xhr({ url: location.href, async: false, credentials: true });\n                this.build(data);\n            }\n            build(d) {\n                this.data = d.includes(\"__INITIAL_STATE__=\") ? JSON.parse(d.match(/INITIAL_STATE__=.+?\\;\\(function/)[0].replace(/INITIAL_STATE__=/, \"\").replace(/;\\(function/, \"\")) : \"\";\n                if (!this.data)\n                    throw \"获取专栏数据失败!\";\n                this.bars();\n                this.upinfo();\n                this.head();\n                this.body();\n                this.tag();\n                this.write();\n            }\n            bars() {\n                this.temp += this.bar.reduce((o, d) => {\n                    o = o + `<a href=\"//www.bilibili.com/read/${d[2]}?from=articleDetail\" target=\"_self\" class=\"tab-item${this.data.readInfo.category.parent_id == d[0] ? \" on\" : \"\"}\" data-tab-id=\"${d[0]}\"><span>${d[1]}</span></a>`;\n                    return o;\n                }, `<div class=\"nav-tab-bar\"><a href=\"https://www.bilibili.com/read/home?from=articleDetail\" target=\"_self\" class=\"logo\"></a>`) + \"</div>\";\n            }\n            upinfo() {\n                this.temp += `<div class=\"up-info-holder\"><div class=\"fixed-box\"><div class=\"up-info-block\">\n            <a class=\"up-face-holder\" href=\"//space.bilibili.com/${this.data.readInfo.author.mid}\" target=\"_blank\"><img class=\"up-face-image\" data-face-src=\"${this.data.readInfo.author.face.replace(\"http:\", \"\")}\" src=\"//static.hdslb.com/images/member/noface.gif\" /></a><div class=\"up-info-right-block\"><div class=\"row\">\n            <a class=\"up-name\" href=\"//space.bilibili.com/${this.data.readInfo.author.mid}\" target=\"_blank\">${this.data.readInfo.author.name}</a> <span class=\"level\"></span><div class=\"nameplate-holder\"><i class=\"nameplate\"></i></div></div><div class=\"row-2\">粉丝: <span class=\"fans-num\"></span> <span class=\"view\">阅读:</span> <span class=\"view-num\"></span></div></div></div><div class=\"follow-btn-holder\"><span class=\"follow-btn\">关注</span></div><div class=\"up-article-list-block hidden\"><div class=\"block-title\">推荐文章</div><ul class=\"article-list\"></ul></div><div class=\"more\"><div class=\"top-bar\"><label>更多</label></div><a class=\"ac-link\" href=\"//www.bilibili.com/read/apply/\" target=\"_blank\"><div class=\"link\"><span class=\"icon\"></span><p class=\"title\">成为创作者</p><p class=\"info\">申请成为专栏UP主</p></div></a> <a href=\"//www.bilibili.com/blackboard/help.html#%C3%A4%C2%B8%C2%93%C3%A6%C2%A0%C2%8F%C3%A7%C2%9B%C2%B8%C3%A5%C2%85%C2%B3\" target=\"_blank\"><div class=\"help\"><span class=\"icon\"></span><p class=\"title\">专栏帮助</p><p class=\"info\">查看专栏使用说明</p></div></a></div></div>\n            </div><div class=\"right-side-bar\"><div class=\"to-comment\"><div class=\"comment-num-holder\"><span class=\"comment-num\"></span></div></div><div class=\"to-top\"></div></div>`;\n            }\n            head() {\n                this.temp += `<div class=\"head-container\"><div class=\"banner-img-holder\"></div><div class=\"bangumi-rating-container\"></div><div class=\"argue-flag hidden\"></div><div class=\"title-container\">\n            <h1 class=\"title\">${this.data.readInfo.title}</h1><div class=\"info\">\n            <a class=\"category-link\" href=\"//www.bilibili.com/read/${this.bar.find(d => {\n                    if (d[0] == this.data.readInfo.category.parent_id)\n                        return d;\n                })[2]}#rid=${this.data.readInfo.category.id}\" target=\"_blank\"><span>${this.data.readInfo.category.name}</span></a> <span class=\"create-time\" data-ts=\"${this.data.readInfo.ctime}\"></span><div class=\"article-data\"></div>\n            </div></div><div style=\"display:none\" class=\"author-container\">\n            <a class=\"author-face\" href=\"//space.bilibili.com/${this.data.readInfo.author.mid}\" target=\"_blank\"><img data-face-src=\"${this.data.readInfo.author.face.replace(\"http:\", \"\")}\" src=\"${this.data.readInfo.author.face.replace(\"http:\", \"\")}\" class=\"author-face-img\" /></a> <a class=\"author-name\" href=\"//space.bilibili.com/${this.data.readInfo.author.mid}\" target=\"_blank\">${this.data.readInfo.author.name}</a><div class=\"attention-btn slim-border\">关注</div></div></div>`;\n            }\n            body() {\n                this.temp += `<div class=\"article-holder\">${this.data.readInfo.content}</div><p class=\"original\">本文为我原创</p>`;\n            }\n            tag() {\n                this.temp += (this.data.readInfo.tags || []).reduce((o, d) => {\n                    o = o + `<li data-tag-id=\"${d.tid}\" class=\"tag-item\"><span class=\"tag-border\"><span class=\"tag-border-inner\"></span></span> <span class=\"tag-content\">${d.name}</span></li>`;\n                    return o;\n                }, `<ul class=\"tag-container\">`) + `</ul><div class=\"article-action\"><div class=\"ops\"><span class=\"like-btn\"><i class=\"icon-video-details_like\"></i> <span>--</span></span> <span class=\"coin-btn\"><i class=\"icon-video-details_throw-coin\"></i> <span>--</span></span> <span class=\"fav-btn\"><i class=\"icon-video-details_collection\"></i> <span>--</span></span> <span class=\"share-container share-btn\">分享到:<span></span></span></div><div class=\"more\"><!-- <i class=\"icon-general_more-actions\"></i> --><div class=\"more-ops-list\"><ul><li value=\"0\">投诉或建议</li></ul></div></div></div><div class=\"article-list-holder-block\"></div><div class=\"draft-holder-block\"></div><div class=\"b-head comment-title-block\"><span class=\"b-head-t comment-results\" style=\"display: inline;\"></span> <span class=\"b-head-t\">评论</span></div><div class=\"comment-holder\"></div>`;\n            }\n            write() {\n                window.original = {\n                    cvid: this.data.cvid,\n                    author: {\n                        name: this.data.readInfo.author.name,\n                        mid: this.data.readInfo.author.mid,\n                    },\n                    banner_url: this.data.readInfo.banner_url || (this.data.readInfo && this.data.readInfo.image_urls[0]) || null,\n                    reprint: this.data.readInfo.reprint,\n                    summary: this.data.readInfo.summary,\n                    media: \"\",\n                    actId: this.data.readInfo.act_id,\n                    dispute: {\n                        dispute: \"\",\n                        dispute_url: \"\"\n                    },\n                    spoiler: \"0\"\n                };\n                this.data = `<div class=\"page-container\">${this.temp}</div>`;\n                API.rewriteHTML(API.getModule(\"read.html\").replace(`<div class=\"page-container\"></div>`, this.data));\n                API.runWhile(() => document.body, () => API.importModule(\"user-select.js\"));\n            }\n        }\n        new Read();\n    }\n    catch (e) {\n        toast.error(\"read.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/read.js";
    modules["watchlater.js"] = "/**\n * 本模块负责重写稍后再看页面\n */\n(function () {\n    try {\n        if (!API.uid)\n            toast.warning(\"未登录,无法启用稍后再看!\");\n        else {\n            API.path.name = \"watchlater\";\n            // 备份还原旧版播放器设置数据\n            API.restorePlayerSetting();\n            API.scriptIntercept([\"video-nano\"]); // 新版播放器拦截\n            API.scriptIntercept([\"stardust-video\"]); // 新版播放器拦截\n            API.rewriteHTML(API.getModule(\"watchlater.html\").replace(\"static.hdslb.com/js/video.min.js\", \"cdn.jsdelivr.net/gh/MotooriKashin/Bilibili-Old/dist/video.min.js\"));\n            API.addCss(API.getModule(\"bofqi.css\"));\n            // 修复评论跳转\n            window.commentAgent = { seek: (t) => window.player && window.player.seek(t) };\n            // 添加点赞功能\n            config.enlike && API.importModule(\"enLike.js\");\n            API.addCss(API.getModule(\"mini-bofqi.css\"));\n            // 修正分区信息\n            API.importModule(\"videoSort.js\");\n            API.path.forEach(d => { d.includes(\"av\") && (API.aid = Number(/[0-9]+/.exec(d)[0])); });\n        }\n    }\n    catch (e) {\n        toast.error(\"watchlater.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/watchlater.js";
    modules["av.js"] = "/**\n * 本模块负责重写av/BV页,由`rewrite.js`按需引导\n * 其他只在重写过的旧版页面生效的功能可添加在本模块中,但更推荐编写在单独的模块中然后将引导代码写在本模块中。\n */\n(function () {\n    try {\n        class Av {\n            constructor() {\n                // __INITIAL_STATE__类型保护\n                this.isAV__INITIAL_STATE__ = (pet) => true;\n                // 重定向SEO页面\n                if (/\\/s\\//.test(location.href))\n                    location.replace(location.href.replace(\"s/video\", \"video\"));\n                API.path.name = \"av\";\n                // 获取aid\n                if (API.path[4].toLowerCase().startsWith('bv'))\n                    API.aid = API.abv(API.path[4].split(\"#\")[0].split(\"?\")[0]);\n                API.aid = API.aid || Number(/[0-9]+/.exec(String(API.path[4]))[0]);\n                config.rewriteMethod == \"异步\" ? this.prepareA() : this.prepareB();\n            }\n            /**\n             * 异步构造__INITIAL_STATE__前置\n             */\n            async prepareA() {\n                await new Promise(r => {\n                    xhr({\n                        url: API.objUrl(\"https://api.bilibili.com/x/web-interface/view/detail\", { aid: API.aid }),\n                        responseType: \"json\",\n                        credentials: true\n                    }).then(d => {\n                        API.importModule(\"av-detail.js\", { __INITIAL_STATE__: d }, true);\n                        r(true);\n                    }).catch(e => {\n                        toast.error(\"获取av号信息出错,尝试访问第三方接口~\", e);\n                        xhr({\n                            url: API.objUrl(\"https://www.biliplus.com/api/view\", { id: API.aid }),\n                            responseType: \"json\"\n                        }).then(d => {\n                            API.importModule(\"av-biliplus.js\", { __INITIAL_STATE__: d }, true);\n                            r(true);\n                        }).catch(e => {\n                            toast.error(\"第三方接口也出错,\", e);\n                            API.importModule(\"vector.js\");\n                        });\n                    });\n                });\n                this.write();\n            }\n            /**\n             * 同步构造__INITIAL_STATE__前置\n             */\n            prepareB() {\n                let d = xhr({\n                    url: API.objUrl(\"https://api.bilibili.com/x/web-interface/view/detail\", { aid: API.aid }),\n                    async: false,\n                    credentials: true\n                });\n                try {\n                    API.importModule(\"av-detail.js\", { __INITIAL_STATE__: d }, true);\n                }\n                catch (e) {\n                    toast.error(\"获取av号信息出错,尝试访问第三方接口~\", e);\n                    d = xhr({\n                        url: API.objUrl(\"https://www.biliplus.com/api/view\", { id: API.aid }),\n                        async: false\n                    });\n                    API.importModule(\"av-biliplus.js\", { __INITIAL_STATE__: d }, true);\n                }\n                this.write();\n            }\n            /**\n             * 实际重写页面过程,依赖__INITIAL_STATE__前置\n             */\n            write() {\n                if (this.isAV__INITIAL_STATE__(API.__INITIAL_STATE__)) {\n                    if (!API.__INITIAL_STATE__)\n                        throw \"无法重写av页 ಥ_ಥ\";\n                    if (API.__INITIAL_STATE__.videoData.redirect_url)\n                        return toast.warning(\"番剧重定向...\", API.__INITIAL_STATE__.videoData.redirect_url);\n                    if (API.__INITIAL_STATE__.videoData.stein_guide_cid)\n                        return (delete API.path.name, toast.warning(\"这似乎是个互动视频!\", \"抱歉!旧版播放器无法支持 ಥ_ಥ\"), API.importModule(\"vector.js\"));\n                    // 备份还原旧版播放器设置数据\n                    API.restorePlayerSetting();\n                    API.scriptIntercept([\"video-nano\"]); // 新版播放器拦截\n                    API.scriptIntercept([\"stardust-video\"]); // 新版播放器拦截\n                    API.aid = API.__INITIAL_STATE__.aid;\n                    API.tid = API.__INITIAL_STATE__.videoData.tid;\n                    window.__INITIAL_STATE__ = API.__INITIAL_STATE__;\n                    config.noVideo && delete window.__playinfo__;\n                    API.rewriteHTML(API.getModule(\"av.html\").replace(\"static.hdslb.com/js/video.min.js\", \"cdn.jsdelivr.net/gh/MotooriKashin/Bilibili-Old/dist/video.min.js\"));\n                    document.title = API.__INITIAL_STATE__.videoData.title + \"_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili\";\n                    API.addCss(API.getModule(\"bofqi.css\"));\n                    // 移除失效顶栏\n                    API.runWhile(() => document.getElementsByClassName(\"bili-header-m report-wrap-module\")[1], () => document.getElementsByClassName(\"bili-header-m report-wrap-module\")[1].remove());\n                    // 修复评论跳转\n                    window.commentAgent = { seek: (t) => window.player && window.player.seek(t) };\n                    // 添加点赞功能\n                    config.enlike && API.importModule(\"enLike.js\");\n                    // 构造媒体页\n                    sessionStorage.getItem(\"medialist\") && API.importModule(\"mediaList.js\");\n                    // 和作UP主\n                    config.upList && API.__INITIAL_STATE__.videoData.staff && API.importModule(\"upList.js\", { staff: API.__INITIAL_STATE__.videoData.staff });\n                    // 视频简介中的bv转超链接\n                    API.importModule(\"descBV.js\");\n                    // 修复原生代码错误\n                    API.importModule(\"hookWebpackJsonp.js\");\n                    // 互动弹幕\n                    config.commandDm && API.importModule(\"commandDm.js\");\n                    // 修正分区信息\n                    API.importModule(\"videoSort.js\");\n                    // 添加媒体控制\n                    API.importModule(\"mediaControl.js\", {\n                        getPlaylistIndex: () => window.player.getPlaylistIndex(),\n                        mediaInfo: (pid, playList) => {\n                            if (this.isAV__INITIAL_STATE__(API.__INITIAL_STATE__))\n                                return {\n                                    title: API.__INITIAL_STATE__.videoData.title,\n                                    artist: API.__INITIAL_STATE__.videoData.owner.name,\n                                    chapterName: playList[pid].part,\n                                    coverUrl: [{ src: API.__INITIAL_STATE__.videoData.pic, sizes: \"320x180\" }]\n                                };\n                        }\n                    });\n                    // 跳过充电鸣谢\n                    config.electric && API.jsonphook([\"api.bilibili.com/x/web-interface/elec/show\"], function (xhr) { xhr.url = API.objUrl(xhr.url.split(\"?\")[0], Object.assign(API.urlObj(xhr.url), { aid: 1, mid: 1 })); });\n                }\n            }\n        }\n        new Av();\n    }\n    catch (e) {\n        debug.error(\"av.js\", e);\n        API.importModule(\"vector.js\");\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/av/av.js";
    modules["commandDm.js"] = "/**\n * 本模块负责实现互动弹幕\n * 告知:本模块由js强行any为ts版本,可能需要进一步优化\n */\n(function () {\n    API.addCss(API.getModule(\"commandDm.css\"));\n    var player, widgetContainer;\n    var playing = false;\n    var visible = true;\n    var commandDm = {\n        visible: [],\n        hidden: [] // 未显示的互动弹幕\n    };\n    /**\n     * 初始化互动弹幕功能\n     */\n    function init() {\n        if (window.__INITIAL_STATE__ && window.__INITIAL_STATE__.videoData && window.player) {\n            if (widgetContainer === undefined)\n                widgetContainer = initCountainer();\n            player = window.player;\n            bindEvents();\n        }\n    }\n    /**\n     * 添加互动弹幕\n     * @param commandDmRaw 从服务器获得的互动弹幕数据\n     */\n    function load(commandDmRaw) {\n        commandDm.hidden = parseDm(commandDmRaw);\n        resize();\n    }\n    /**\n     * 创建互动弹幕的容器div\n     * @returns div.bilibili-player-video-popup\n     */\n    function initCountainer() {\n        let videoWrap = document.getElementsByClassName(\"bilibili-player-video-wrap\")[0];\n        if (!videoWrap)\n            return;\n        let widgetContainer = document.createElement(\"div\");\n        widgetContainer.className = \"bilibili-player-video-popup\";\n        videoWrap.appendChild(widgetContainer);\n        return widgetContainer;\n    }\n    /**\n     * 绑定播放器事件,使用window.player.addEventListener\n     */\n    function bindEvents() {\n        const EVENT = {\n            VIDEO_MEDIA_PLAYING: \"video_media_playing\",\n            VIDEO_MEDIA_PAUSE: \"video_media_pause\",\n            VIDEO_MEDIA_SEEK: \"video_media_seek\",\n            VIDEO_MEDIA_SEEKED: \"video_media_seeked\",\n            VIDEO_MEDIA_ENDED: \"video_media_ended\",\n            VIDEO_RESIZE: \"video_resize\",\n            VIDEO_PLAYER_RESIZE: \"video_player_resize\",\n            VIDEO_DESTROY: \"video_destroy\"\n        };\n        player.addEventListener(EVENT.VIDEO_MEDIA_PLAYING, play);\n        player.addEventListener(EVENT.VIDEO_MEDIA_PAUSE, pause);\n        player.addEventListener(EVENT.VIDEO_MEDIA_SEEK, pause);\n        player.addEventListener(EVENT.VIDEO_MEDIA_SEEKED, play);\n        player.addEventListener(EVENT.VIDEO_MEDIA_ENDED, pause);\n        player.addEventListener(EVENT.VIDEO_PLAYER_RESIZE, resize);\n        player.addEventListener(EVENT.VIDEO_DESTROY, destroy);\n        // 开启/关闭弹幕事件\n        document.querySelector(\"div.bilibili-player-video-control > div.bilibili-player-video-btn.bilibili-player-video-btn-danmaku\").addEventListener(\"click\", (event) => {\n            let option = event.target.getAttribute(\"name\");\n            if (option == \"ctlbar_danmuku_close\") {\n                visible = false;\n                pause();\n                widgetContainer.style.display = \"none\";\n            }\n            else if (option == \"ctlbar_danmuku_on\") {\n                visible = true;\n                play();\n                widgetContainer.style.display = \"\";\n            }\n        });\n    }\n    /**\n     * 生成互动弹幕的UI组件,各种后续处理\n     * @param commandDmRaw 互动弹幕原始数据\n     * @returns 互动弹窗的UI对象\n     */\n    function parseDm(commandDmRaw) {\n        let popupWindow = [];\n        for (let i = 0, cdm, extra, from; i < commandDmRaw.length; i++) {\n            cdm = commandDmRaw[i];\n            extra = JSON.parse(cdm.extra);\n            from = cdm.progress / 1000;\n            switch (cdm.command) {\n                // 4种将会弹出界面的互动弹幕(见原生代码appendPopup())\n                case \"#ATTENTION#\":\n                    break;\n                case \"#ACTORFOLLOW#\":\n                case \"#MANAGERFOLLOW#\":\n                    break;\n                case \"#VOTE#\": // 投票弹窗\n                    popupWindow.push(new Vote(cdm, extra, from));\n                    break;\n                case \"#GRADE#\": // 评分弹窗\n                    popupWindow.push(new Grade(cdm, extra, from));\n                    break;\n                // 滚动弹幕(见原生代码appendDmImg()),它们的渲染也许需要去修改原生弹幕渲染器\n                case \"#RESERVE#\":\n                    break;\n                case \"#LINK#\":\n                    popupWindow.push(new Link(cdm, extra, from));\n                    break;\n                case \"#ACTOR#\":\n                    break;\n                case \"#ACTIVITYCOMBO#\":\n                    break;\n            }\n        }\n        return popupWindow;\n    }\n    function play() {\n        if (visible) {\n            playing = true;\n            loop();\n        }\n    }\n    function pause() {\n        playing = false;\n        loop();\n    }\n    /**\n     * 播放器大小更改时触发\n     */\n    function resize() {\n        // 获得当前播放器显示分辨率与最小分辨率(680x504)时的缩放比,用于UI缩放\n        let scaleX = widgetContainer.clientWidth / 680;\n        let scaleY = widgetContainer.clientHeight / 504;\n        for (let i = 0; i < commandDm.visible.length; i++) {\n            commandDm.visible[i].resize(scaleX, scaleY);\n        }\n        for (let i = 0; i < commandDm.hidden.length; i++) {\n            commandDm.hidden[i].resize(scaleX, scaleY);\n        }\n    }\n    function loop() {\n        let time = player.getCurrentTime(); // 获得以秒为单位的当前播放进度\n        if (playing) {\n            requestAnimationFrame(loop);\n        }\n        // 根据播放进度,显示、隐藏互动弹幕界面\n        for (let i = 0, cdm; i < commandDm.hidden.length; i++) {\n            cdm = commandDm.hidden[i];\n            if (cdm.from < time && cdm.to > time) {\n                commandDm.visible.push(cdm);\n                commandDm.hidden.splice(i, 1);\n                cdm.show();\n            }\n        }\n        for (let i = 0, cdm; i < commandDm.visible.length; i++) {\n            cdm = commandDm.visible[i];\n            if (cdm.to < time || cdm.from > time) {\n                commandDm.hidden.push(cdm);\n                commandDm.visible.splice(i, 1);\n                cdm.hide();\n            }\n        }\n    }\n    function destroy() {\n        playing = false;\n        for (let i = 0; i < commandDm.visible.length; i++) {\n            commandDm.visible[i].destroy();\n        }\n        for (let i = 0; i < commandDm.hidden.length; i++) {\n            commandDm.hidden[i].destroy();\n        }\n        commandDm.visible.splice(0, commandDm.visible.length);\n        commandDm.hidden.splice(0, commandDm.hidden.length);\n    }\n    function divClass(className) {\n        let div = document.createElement(\"div\");\n        div.className = className;\n        return div;\n    }\n    function isLoggedin() {\n        if (API.uid)\n            return true;\n        player.pause();\n        toast.warning(\"请先登录\");\n        API.biliQuickLogin();\n    }\n    function post(url, data, contentType = \"application/x-www-form-urlencoded;charset=UTF-8\") {\n        data.csrf = API.getCookies().bili_jct;\n        return xhr({\n            url: url,\n            data: API.objUrl(\"\", data),\n            headers: { \"Content-Type\": contentType },\n            method: \"POST\",\n            credentials: true\n        });\n    }\n    /**\n     * 弹窗组件\n     */\n    class PopupWindow {\n        constructor(cdm, extra, from) {\n            this.duration = extra.duration / 1e3 || 5;\n            this.from = from || 0;\n            this.to = from + (extra.duration / 1e3 || 5);\n            this.pos_x = extra.posX || 200;\n            this.pos_y = extra.posY || 200;\n            this.popup = divClass(\"commandDm-popup\");\n            this.popup.style.display = \"none\";\n            widgetContainer.appendChild(this.popup);\n        }\n        show() {\n            this.popup.style.display = \"\";\n            requestAnimationFrame(() => this.popup.className = \"commandDm-popup on\");\n        }\n        hide() {\n            this.popup.className = \"commandDm-popup\";\n            setTimeout(() => this.popup.style.display = \"none\", 200);\n        }\n        destroy() {\n        }\n        /**\n        * 根据视频区域大小等比缩放投票界面\n        */\n        resize(scaleX, scaleY) {\n            this.popup.style.left = (this.pos_x * scaleX) + \"px\";\n            this.popup.style.top = (this.pos_y * scaleY) + \"px\";\n            this.popup.style.transform = \"translateX(-50%) translateY(-50%) scale(\" + Math.min((scaleX + scaleY) / 2, 1.5) + \")\";\n        }\n    }\n    /**\n     * 投票互动UI\n     */\n    class Vote extends PopupWindow {\n        constructor(cdm, extra, from) {\n            super(cdm, extra, from);\n            this.popup.style.width = \"150px\";\n            this.total = extra.cnt;\n            this.voteId = extra.vote_id;\n            this.options = extra.options;\n            this.question = extra.question;\n            this.myVote = extra.my_vote; // 0:未投票  非零数字:已投票,my_vote的值即为已投项的idx\n            let dialog = divClass(\"vote-dialog\");\n            let panel = divClass(\"vote-panel\");\n            let title = divClass(\"vote-title\");\n            title.innerHTML = this.question;\n            let optionDiv = divClass(\"vote-option\");\n            let button = [];\n            for (let i = 0, btn, opt; i < this.options.length; i++) {\n                // 投票按钮\n                opt = this.options[i];\n                btn = divClass(\"vote-button\");\n                btn.innerHTML = opt.desc;\n                btn.setAttribute(\"idx\", opt.idx);\n                btn.onclick = () => this.goVote(opt.idx, i);\n                button[i] = btn;\n                optionDiv.appendChild(btn);\n            }\n            panel.appendChild(optionDiv);\n            dialog.appendChild(title);\n            dialog.appendChild(panel);\n            this.popup.appendChild(dialog);\n            this.dialog = dialog;\n            this.button = button;\n            this.progress = [];\n            // 已投票则直接显示结果\n            if (this.myVote !== 0) {\n                this.showResult();\n                this.progress[this.myVote - 1].className = \"vote-progress vote-progress-blue\";\n            }\n            ;\n        }\n        goVote(idx, i) {\n            if (isLoggedin()) {\n                this.total += 1;\n                this.options[i].cnt += 1;\n                // 发送投票操作到服务器\n                let url = \"//api.bilibili.com/x/web-interface/view/dm/vote\";\n                post(url, {\n                    aid: API.aid,\n                    cid: API.cid,\n                    progress: Math.max(Math.round(1e3 * player.getCurrentTime()), 1),\n                    vote: idx,\n                    vote_id: this.voteId\n                }).then((resp) => {\n                    resp = JSON.parse(resp);\n                    biliAPI.verify(resp, \"投票\");\n                    this.progress[i].className = \"vote-progress vote-progress-blue\";\n                });\n                this.myVote = idx;\n                this.showResult();\n                this.to += 5; //点击投票后推迟5秒消失,防止结果消失太快来不及看\n            }\n        }\n        showResult() {\n            // 显示票数、比例条\n            this.count = [];\n            for (let i = 0, progress, desc; i < this.button.length; i++) {\n                this.button[i].onclick = null;\n                this.button[i].innerHTML = \"\";\n                this.button[i].className = \"vote-progress-bg\";\n                progress = divClass(\"vote-progress\");\n                desc = divClass(\"vote-progress-desc\");\n                desc.innerHTML = this.options[i].desc;\n                progress.appendChild(desc);\n                this.button[i].appendChild(progress);\n                this.progress[i] = progress;\n                // 结果数据\n                let cnt = divClass(\"vote-count\");\n                cnt.innerHTML = this.options[i].cnt;\n                this.count[i] = cnt;\n                this.button[i].appendChild(cnt);\n            }\n            this.resultAnimation();\n        }\n        /**\n         * 投票结果的动画\n         */\n        resultAnimation() {\n            // 投票比例条型图向右展开\n            for (let i = 0; i < this.progress.length; i++) {\n                this.progress[i].style.width = \"0\";\n                requestAnimationFrame(() => this.progress[i].style.width = (this.options[i].cnt / this.total * 100) + \"%\");\n            }\n            // 右侧票数递增动画,持续0.8秒\n            let start = performance.now();\n            let frame = (t) => {\n                let percentage = (t - start) * 0.00125;\n                if (percentage < 1)\n                    requestAnimationFrame(frame);\n                else\n                    percentage = 1;\n                for (let i = 0; i < this.count.length; i++) {\n                    this.count[i].innerHTML = Math.floor(this.options[i].cnt * percentage);\n                }\n            };\n            requestAnimationFrame(frame);\n        }\n        show() {\n            super.show();\n            if (this.myVote !== 0) {\n                this.resultAnimation();\n            }\n        }\n        hide() {\n            super.hide();\n            this.to = this.from + this.duration; // 重设消失时间\n        }\n    }\n    class Grade extends PopupWindow {\n        constructor(cdm, info, from) {\n            super(cdm, info, from);\n            this.popup.style.width = \"184px\";\n            this.gradeInfo = info;\n            this.popup.innerHTML = `\n            <div style=\"display:block\" class=\"grade-title\">${info.msg}</div>\n            <div class=\"grade-score-area pointer\"></div>\n            <div class=\"grade-score-info\" style=\"display:none\">\n                <div style=\"color:#6f6f6f;display:inline-block;\">平均</div><span style=\"color:${info.skin_font_color};font-size:27px\" class=\"grade-avg-score\">${info.avg_score}</span>\n            </div>\n            <span style=\"position:absolute;right:1rem;top:0.8rem;font-size:12px;color:#6f6f6f\" class=\"grade-score-count\">${info.count}人参与</span>\n            `;\n            this.scoreInfo = this.popup.getElementsByClassName(\"grade-score-info\")[0];\n            let scoreArea = this.popup.getElementsByClassName(\"grade-score-area\")[0];\n            let scoreButton = [];\n            function highlightScores(i) {\n                for (let m = 0; m < 5; m++) {\n                    if (m <= i && !scoreButton[m].highlight) {\n                        scoreButton[m].highlight = true;\n                        scoreButton[m].className = \"highlight\";\n                    }\n                    else if (m > i && scoreButton[m].highlight) {\n                        scoreButton[m].highlight = false;\n                        scoreButton[m].className = \"\";\n                    }\n                }\n            }\n            for (let i = 0; i < 5; i++) {\n                let score = document.createElement(\"div\");\n                scoreButton[i] = score;\n                score.innerHTML = `\n                <img width=20 hegiht=20 src=\"${info.skin_selected}\" class=\"bg\"></img>\n                <img width=20 hegiht=20 src=\"${info.skin_selected}\" class=\"score-button\"></img>`;\n                scoreArea.appendChild(score);\n                if (info.mid_score === 0) {\n                    score.onmouseenter = () => highlightScores(i);\n                    score.onclick = () => {\n                        if (isLoggedin()) {\n                            this.gradeInfo.avg_score = (this.gradeInfo.count * this.gradeInfo.avg_score + (i + 1) * 2) / (this.gradeInfo.count + 1);\n                            this.gradeInfo.avg_score = this.gradeInfo.avg_score.toPrecision(2);\n                            this.gradeInfo.count += 1;\n                            this.popup.getElementsByClassName(\"grade-avg-score\")[0].innerHTML = this.gradeInfo.avg_score;\n                            this.popup.getElementsByClassName(\"grade-score-count\")[0].innerHTML = this.gradeInfo.count + \"人参与\";\n                            this.showResult();\n                            for (let index = 0; index < 5; index++) {\n                                if (index <= i) {\n                                    scoreButton[index].style.animation = \"grade-score-hit 0.7s ease forwards\";\n                                    setTimeout(() => scoreButton[index].style.animation = \"\", 1000);\n                                }\n                                scoreButton[index].onclick = null;\n                                scoreButton[index].onmouseenter = null;\n                            }\n                            scoreArea.onmouseleave = null;\n                            scoreArea.classList.remove(\"pointer\");\n                            this.goGrade((i + 1) * 2);\n                        }\n                    };\n                }\n            }\n            ;\n            if (info.mid_score === 0)\n                scoreArea.onmouseleave = () => highlightScores(-1);\n            this.scoreButton = scoreButton;\n            if (info.mid_score != 0) {\n                this.showResult();\n                highlightScores(info.mid_score / 2 - 1);\n                scoreArea.classList.remove(\"pointer\");\n            }\n        }\n        goGrade(score) {\n            post(\"https://api.bilibili.com/x/v2/dm/command/grade/post\", {\n                aid: API.aid,\n                cid: API.cid,\n                progress: parseInt(player.getCurrentTime()) * 1000,\n                grade_id: this.gradeInfo.grade_id,\n                grade_score: score\n            });\n            this.to += 3;\n        }\n        showResult() {\n            this.scoreInfo.style.display = \"\";\n            this.scoreInfo.style.animation = \"grade-score-showup 0.3s ease 0.2s forwards\";\n            for (let i = 0; i < 4; i++) {\n                setTimeout(() => this.scoreButton[i].style.width = \"24px\", i * 50);\n            }\n        }\n        hide() {\n            super.hide();\n            this.to = this.from + this.duration;\n        }\n    }\n    /**\n     * 用于获取收藏列表有关信息\n     */\n    class favList {\n        static get() {\n            if (this.list.length > 0)\n                return Promise.resolve(this.list);\n            return xhr({\n                url: API.objUrl(\"//api.bilibili.com/x/v3/fav/folder/created/list-all\", {\n                    type: String(2),\n                    rid: String(API.aid),\n                    up_mid: String(API.uid)\n                }),\n                credentials: true\n            }).then((resp) => {\n                resp = JSON.parse(resp);\n                biliAPI.verify(resp, \"获取收藏列表\");\n                this.list = resp.data.list;\n                this.list.forEach((v) => v.attr === 1 && (this.defaultFolderId = v.id));\n                return this.list;\n            });\n        }\n        static getDefaultFolder() {\n            if (this.defaultFolderId !== 0)\n                return Promise.resolve(this.defaultFolderId);\n            return this.get().then(() => { return this.defaultFolderId; });\n        }\n    }\n    favList.list = [];\n    favList.defaultFolderId = 0;\n    /**\n     * @see https://github.com/SocialSisterYi/bilibili-API-collect\n     */\n    class biliAPI {\n        static verify(resp, msg) {\n            if (resp.code !== 0) {\n                toast.error(msg + \"失败\", resp.code, resp.message);\n                throw msg + \"失败\";\n            }\n            return resp;\n        }\n        static like(bool) {\n            bool = bool ? 1 : 2;\n            return post(\"//api.bilibili.com/x/web-interface/archive/like\", {\n                aid: API.aid,\n                like: bool\n            }, \"application/json; charset=utf-8\").then((resp) => biliAPI.verify(resp, \"点赞\"));\n        }\n        static follow() {\n            return post(\"//api.bilibili.com/x/relation/modify\", {\n                aid: API.aid,\n                fid: window.getAuthorInfo().mid,\n                act: 1,\n                re_src: 14\n            }).then((resp) => {\n                resp = JSON.parse(resp);\n                return biliAPI.verify(resp, \"关注\");\n            });\n        }\n        static coin() {\n        }\n        static fav() {\n            return post(\"//api.bilibili.com/x/v3/fav/resource/deal\", {\n                rid: API.aid,\n                type: 2,\n                add_media_ids: favList.defaultFolderId,\n            }).then((resp) => {\n                resp = JSON.parse(resp);\n                return biliAPI.verify(resp, \"收藏\");\n            });\n        }\n        static triple() {\n            return post(\"//api.bilibili.com/x/web-interface/archive/like/triple\", {\n                aid: API.aid\n            }, \"application/json; charset=utf-8\").then((resp) => {\n                biliAPI.verify(resp, \"三连\");\n                var d = resp.data;\n                if (d.coin && d.like && d.fav)\n                    return;\n                if (!d.coin)\n                    toast.error(\"投币失败\");\n                if (!d.like)\n                    toast.error(\"点赞失败\");\n                if (!d.fav)\n                    toast.error(\"收藏失败\");\n                return d;\n            });\n        }\n    }\n    /**\n     * 关联视频跳转按钮\n     */\n    class Link {\n        constructor(cdm, extra, from) {\n            this.content = cdm.content;\n            this.aid = extra.aid;\n            this.from = from || 0;\n            this.to = from + 5;\n            this.pos_x = extra.posX || 200;\n            this.pos_y = extra.posY || 200;\n            /*\n                <div class=\"link-button\">\n                    <img src=\"https://static.hdslb.com/images/favicon.ico\">\n                    <span>关联视频跳转</span>\n                </div>\n            */\n            let button = divClass(\"link-button\");\n            let img = document.createElement(\"img\");\n            img.src = \"https://static.hdslb.com/images/favicon.ico\";\n            let span = document.createElement(\"span\");\n            span.innerHTML = this.content;\n            button.appendChild(img);\n            button.appendChild(span);\n            button.style.display = \"none\";\n            button.onclick = () => {\n                player.pause();\n                window.open(\"https://www.bilibili.com/video/av\" + this.aid);\n            };\n            widgetContainer.appendChild(button);\n            this.button = button;\n        }\n        show() {\n            this.button.style.display = \"block\";\n        }\n        hide() {\n            this.button.style.display = \"none\";\n        }\n        /**\n         * 根据视频区域大小缩放,放大倍数限制在最大1.5倍\n         */\n        resize(scaleX, scaleY) {\n            this.button.style.left = (this.pos_x * scaleX) + \"px\";\n            this.button.style.top = (this.pos_y * scaleY) + \"px\";\n            this.button.style.transform = \"translateX(-50%) translateY(-50%) scale(\" + Math.min(1.5, (scaleX + scaleY) / 2) + \")\";\n        }\n        destroy() {\n        }\n    }\n    /**\n     * 程序入口\n     * @param cdm 互动弹幕原始数据\n     * @param aid aid\n     * @param cid cid\n     */\n    API.loadCommandDm = async (cdm, aid, cid) => {\n        try {\n            if (aid != API.aid || cid != API.cid || widgetContainer !== undefined) {\n                // 正在“载入其他视频弹幕”,不必处理互动弹幕\n                return;\n            }\n            init(); // 由于切P后整个播放器会被销毁重建,每次载入互动弹幕都需要重新绑定事件\n            load(cdm);\n        }\n        catch (e) {\n            toast.error(\"commandDm.js\", e);\n        }\n    };\n})();\n\n//# sourceURL=API://@bilibili/dist/match/av/commandDm.js";
    modules["descBV.js"] = "/**\n * 本模块负责转化av页简介中BV号为超链接\n */\n(function () {\n    try {\n        API.switchVideo(() => {\n            let desc = document.getElementsByClassName(\"info\");\n            if (desc[1] && desc[1].parentNode && desc[1].parentNode.id == \"v_desc\") {\n                let text = desc[1].innerText;\n                text = text.replace(/BV[A-Za-z0-9]+/gi, (str) => {\n                    const av = API.abv(str);\n                    return `<a target=\"_blank\" href=\"//www.bilibili.com/video/av${av}\">av${av}</a>`;\n                }).replace(/AV[0-9]+/g, (str) => {\n                    str = str.toLowerCase();\n                    return `<a target=\"_blank\" href=\"//www.bilibili.com/video/${str}\">${str}</a>`;\n                });\n                desc[1].innerHTML = text;\n            }\n        });\n    }\n    catch (e) {\n        debug.error(\"descBV.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/av/descBV.js";
    modules["enLike.js"] = "/**\n * 本模块负责为旧版av/BV、稍后再看添加点赞功能\n */\n(function () {\n    API.runWhile(() => document.querySelector(\".v.play\"), async () => {\n        try {\n            let span = document.createElement(\"span\");\n            let like = `background-image: url(//cdn.jsdelivr.net/gh/MotooriKashin/Bilibili-Old/image/like.png);`;\n            let dislike = `background-image: url(//cdn.jsdelivr.net/gh/MotooriKashin/Bilibili-Old/image/dislike.png);`;\n            let text = document.createTextNode(\"点赞 --\");\n            let arg = text;\n            let islike = false;\n            let i = API.addElement(\"i\", { class: \"l-icon-move\", style: 'width : 22px;height : 22px;display: inline-block;vertical-align: middle;margin-top: -3px;margin-right: 3px;' + dislike }, span);\n            let b = API.addElement(\"b\", { class: \"l-icon-moved\", style: \"width : 22px;height : 22px;display : none;\" }, span);\n            span.setAttribute(\"class\", \"u like\");\n            span.setAttribute(\"style\", \"margin-left : 24px;margin-right : 10px;\");\n            span.appendChild(text);\n            document.querySelector(\".number\").insertBefore(span, document.querySelector(\".coin\"));\n            span.onclick = async () => {\n                if (islike) {\n                    // 取消点赞\n                    let data = await xhr({\n                        url: \"https://api.bilibili.com/x/web-interface/archive/like\",\n                        method: \"POST\",\n                        data: `aid=${API.aid}&like=2&csrf=${API.getCookies().bili_jct}`,\n                        credentials: true\n                    });\n                    data = API.jsonCheck(data).ttl;\n                    toast.warning(\"取消点赞!\");\n                    islike = false;\n                    i.setAttribute(\"style\", \"width : 22px;height : 22px;display: inline-block;vertical-align: middle;margin-top: -3px;margin-right: 3px;\" + dislike);\n                    b.setAttribute(\"style\", \"width : 22px;height : 22px;display : none;\");\n                    if (arg.nodeValue.match(\"万\"))\n                        return;\n                    let number = 1 * arg.nodeValue.match(/[0-9]+/) - 1;\n                    text = document.createTextNode(\" 点赞 \" + number);\n                    arg.replaceWith(text);\n                    arg = text;\n                }\n                else {\n                    if (!API.uid)\n                        return API.biliQuickLogin(); // 登录判断\n                    // 点赞\n                    let data = await xhr({\n                        url: \"https://api.bilibili.com/x/web-interface/archive/like\",\n                        method: \"POST\",\n                        data: `aid=${API.aid}&like=1&csrf=${API.getCookies().bili_jct}`,\n                        credentials: true\n                    });\n                    data = API.jsonCheck(data).ttl;\n                    toast.success(\"点赞成功!\");\n                    islike = true;\n                    i.setAttribute(\"style\", \"width : 22px;height : 22px;display : none;\");\n                    b.setAttribute(\"style\", \"width : 22px;height : 22px;display: inline-block;vertical-align: middle;margin-top: -3px;margin-right: 3px;\" + like);\n                    if (arg.nodeValue.match(\"万\"))\n                        return;\n                    let number = 1 * arg.nodeValue.match(/[0-9]+/) + 1;\n                    text = document.createTextNode(\" 点赞 \" + number);\n                    arg.replaceWith(text);\n                    arg = text;\n                }\n            };\n            // 初始化按钮\n            let data = await xhr({\n                url: API.objUrl(\"https://api.bilibili.com/x/web-interface/view\", { aid: API.aid }),\n                credentials: true\n            });\n            data = API.jsonCheck(data).data.stat.like;\n            document.querySelector(\".like\").setAttribute(\"title\", \"点赞人数\" + data);\n            text = document.createTextNode(\" 点赞 \" + API.unitFormat(data));\n            arg.replaceWith(text);\n            arg = text;\n            if (!API.uid)\n                return;\n            data = API.jsonCheck(await xhr({\n                url: API.objUrl(\"https://api.bilibili.com/x/web-interface/archive/has/like\", { \"aid\": API.aid }),\n                credentials: true\n            })).data;\n            if (data == 1) {\n                // 点赞过点亮图标\n                i.setAttribute(\"style\", \"width : 22px;height : 22px;display : none;\");\n                b.setAttribute(\"style\", \"width : 22px;height : 22px;display: inline-block;vertical-align: middle;margin-top: -3px;margin-right: 3px;\" + like);\n                islike = true;\n            }\n        }\n        catch (e) {\n            toast.error(\"enLike.js\", e);\n        }\n    });\n})();\n\n//# sourceURL=API://@bilibili/dist/match/av/enLike.js";
    modules["hookWebpackJsonp.js"] = "/**\n * 本模块负责修复av页原生脚本中的错误代码\n */\n(function () {\n    try {\n        let webpackJsonpFunction;\n        Object.defineProperty(window, \"webpackJsonp\", {\n            get() {\n                if (webpackJsonpFunction) {\n                    return (chunkIds, moreModules, executeModules) => {\n                        function inject(index, replaceFn) {\n                            let code = moreModules[index].toString();\n                            moreModules[index] = new Function(\"t\", \"e\", \"i\", \"(\" + replaceFn(code) + \")(t,e,i)\");\n                        }\n                        // length == 716 -> vendor.js\n                        //        == 717 -> video.b1b7706abd590dd295794f540f7669a5d8d978b3.js\n                        if (moreModules.length == 717) {\n                            // 暴露UI组件\n                            // .onCoinSuccess(n)   页面变为已投币n枚的状态\n                            // .onFollow()         变为已关注状态\n                            // .favSubmit(bool)    设置收藏状态,参数bool: true -> “已收藏”状态 false -> 未收藏状态\n                            inject(274, (code) => code.replace(\"init:function(){\", \"init:function(){window.biliUIcomponents=this;\"));\n                            // 修复:收藏视频时,在“添加到收藏夹”弹窗中,如果将视频从收藏夹A删除,并同时添加到收藏夹B,点击确定后窗口不消失的问题\n                            /* 报错原因示意:\n                                jQuery.when(deferredA,deferredB).done((resultA,resultB) => {\n                                    let codeA = resultA[0].code; // Cannot read property 'code' of undefined\n                                    let codeA = resultA.code;    // 本应该写成这样\n                                })\n                            */\n                            inject(251, (code) => code.replace(\"e[0].code\", \"e.code\").replace(\"i[0].code\", \"i.code\"));\n                        }\n                        return webpackJsonpFunction(chunkIds, moreModules, executeModules);\n                    };\n                }\n            },\n            set(func) {\n                webpackJsonpFunction = func;\n            }\n        });\n    }\n    catch (e) {\n        toast.error(\"webpackJsonpFunction.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/av/hookWebpackJsonp.js";
    modules["loadByDmid.js"] = "/**\n * 本模块负责处理dmid跳转\n */\n(function () {\n    try {\n        const dmid = API.urlObj(location.href).dmid;\n        let progress = Number(API.urlObj(location.href).dm_progress);\n        let first = 0;\n        API.switchVideo(async () => {\n            var _a;\n            if (!((_a = window.player) === null || _a === void 0 ? void 0 : _a.seek)) {\n                await new Promise(r => {\n                    API.runWhile(() => { var _a; return (_a = window.player) === null || _a === void 0 ? void 0 : _a.seek; }, r);\n                });\n            }\n            if (first)\n                return;\n            first++;\n            if (progress)\n                return window.player.seek(progress);\n            if (dmid) {\n                progress = await xhr({\n                    url: `https://api.bilibili.com/x/v2/dm/thumbup/detail?oid=${API.cid}&dmid=${dmid}`,\n                    credentials: true\n                });\n                progress = API.jsonCheck(progress).data.progress; // 检查xhr返回值并转化为json\n                progress && window.player.seek(progress / 1000 - .2);\n            }\n        });\n    }\n    catch (e) {\n        debug.error(\"loadByDmid.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/av/loadByDmid.js";
    modules["mediaControl.js"] = "/**\n * 本模块负责为旧版播放器添加媒体控制键\n * 请以`mediaInfo`、`getPlaylistIndex`的名义传入数据\n * 告知:本模块由js强行any为ts版本,可能需要进一步优化\n */\n(async function mediaControl() {\n    try {\n        // 等待播放器正式加载\n        if (document.visibilityState !== \"visible\") {\n            let listener = () => {\n                document.removeEventListener(\"visibilitychange\", listener);\n                mediaControl();\n            };\n            document.addEventListener(\"visibilitychange\", listener);\n        }\n        else if (\"mediaSession\" in window.navigator) {\n            function trial(fn) {\n                let limit = 7;\n                function task() { if (!fn() && --limit > 0)\n                    setTimeout(task, 1000); }\n                task();\n            }\n            trial(() => {\n                // 确保播放器和播放列表已经加载\n                if (window.player != undefined && window.player.getPlaylist && window.player.getPlaylist() != null) {\n                    // @ts-ignore:该变量由主模块传入\n                    let LastPid = getPlaylistIndex();\n                    // @ts-ignore:该变量由主模块传入\n                    let info = mediaInfo(LastPid, window.player.getPlaylist());\n                    navigator.mediaSession.metadata = new MediaMetadata({\n                        title: info.title,\n                        artist: info.artist,\n                        album: info.chapterName,\n                        artwork: info.coverUrl\n                    });\n                    navigator.mediaSession.setActionHandler('play', () => window.player.play());\n                    navigator.mediaSession.setActionHandler('pause', () => window.player.pause());\n                    navigator.mediaSession.setActionHandler('seekbackward', () => window.player.seek(window.player.getCurrentTime() - 10));\n                    navigator.mediaSession.setActionHandler('seekforward', () => window.player.seek(window.player.getCurrentTime() + 10));\n                    navigator.mediaSession.setActionHandler('previoustrack', () => window.player.prev());\n                    navigator.mediaSession.setActionHandler('nexttrack', () => window.player.next());\n                    let playList = window.player.getPlaylist();\n                    API.switchVideo(() => {\n                        // 要等到新的分p载入完成,getPlaylistIndex()的值才会更新\n                        trial(() => {\n                            // @ts-ignore:该变量由主模块传入\n                            let pid = getPlaylistIndex();\n                            if (pid != LastPid && window.player.getPlaylist() != undefined) {\n                                LastPid = pid;\n                                // @ts-ignore:该变量由主模块传入\n                                info = mediaInfo(LastPid, window.player.getPlaylist());\n                                navigator.mediaSession.metadata.title = info.title;\n                                navigator.mediaSession.metadata.artist = info.artist;\n                                navigator.mediaSession.metadata.album = info.chapterName;\n                                navigator.mediaSession.metadata.artwork = info.coverUrl;\n                                return true;\n                            }\n                        });\n                    });\n                    return true;\n                }\n            });\n        }\n    }\n    catch (e) {\n        toast.error(\"mediaControl.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/av/mediaControl.js";
    modules["mediaList.js"] = "/**\n * 本模块负责基于av页重构为媒体页\n */\n(function () {\n    if (config.medialist && /\\/medialist\\/play\\//.test(location.href)) {\n        if (/ml\\d+/.test(location.href)) {\n            API.xhrhook([\"medialist/resource/list?\", \"biz_id\"], function (args) {\n                const obj = API.urlObj(args[1]);\n                sessionStorage.setItem(\"medialist\", obj.biz_id);\n                this.addEventListener(\"readystatechange\", () => {\n                    if (this.readyState === 4) {\n                        if (!this.response)\n                            throw this;\n                        const response = API.jsonCheck(this.response);\n                        response.data && response.data.media_list && location.replace(`https://www.bilibili.com/video/av${response.data.media_list[0].id}`);\n                    }\n                });\n            });\n        }\n        else\n            toast.warning(\"抱歉!\", `这不是一个固定的媒体播放列表,已禁用旧版模拟!`);\n    }\n    // 新版稍后再看跳转到旧版稍后再看\n    if (API.path[5] && API.path[5].startsWith(\"watchlater\") && config.watchlater)\n        location.replace(\"https://www.bilibili.com/watchlater/#/\");\n    if (!/\\/video\\/[AaBb][Vv]/.test(location.href))\n        return;\n    let mid = sessionStorage.getItem(\"medialist\");\n    sessionStorage.removeItem(\"medialist\");\n    try {\n        toast(\"重构媒体页信息中...\");\n        let avs = [], value = [], promises = [], ids = [];\n        xhr({\n            url: `https://api.bilibili.com/x/v1/medialist/resource/ids4Player?media_id=${mid}`,\n            credentials: true\n        }).then(async (d) => {\n            let data = API.jsonCheck(d).data;\n            for (let i = 0; i < data.medias.length; i++) {\n                ids[i] = data.medias[i].id;\n                avs[i] = \"av\" + data.medias[i].id;\n            }\n            // 同时获取所有aid对应的数据,使用Promise.all对齐,该api会直接忽略失效视频\n            while (avs.length) {\n                let i = avs.length > 20 ? 20 : avs.length;\n                value = avs.splice(0, i);\n                promises.push(xhr({\n                    url: API.objUrl(\"https://api.bilibili.com/x/article/cards\", { \"ids\": value.join(\"%2C\") }),\n                    credentials: true\n                }));\n            }\n            value = [];\n            data = await Promise.all(promises);\n            // 格式化数据并排序\n            for (let i = 0; i < data.length; i++) {\n                data[i] = API.jsonCheck(data[i]);\n                for (let key in data[i].data)\n                    avs.push(data[i].data[key]);\n            }\n            for (let i = 0; i < ids.length; i++) {\n                for (let j = 0; j < avs.length; j++) {\n                    if (avs[j].aid == ids[i]) {\n                        value.push(avs[j]);\n                        break;\n                    }\n                }\n            }\n            ids = value;\n            API.runWhile(() => window.BilibiliPlayer, () => {\n                // 将视频列表重构为稍后再看列表\n                for (let i = 0; i < ids.length; i++) {\n                    ids[i].progress = 0;\n                    ids[i].add_at = ids[i].ctime;\n                    ids[i].pages = [];\n                    ids[i].pages[0] = {};\n                    ids[i].pages[0].cid = ids[i].cid;\n                    ids[i].pages[0].dimension = ids[i].dimension;\n                    ids[i].pages[0].duration = ids[i].duration;\n                    ids[i].pages[0].from = \"vupload\";\n                    ids[i].pages[0].page = 1;\n                    ids[i].pages[0].part = ids[i].title;\n                    ids[i].pages[0].vid = \"\";\n                    ids[i].pages[0].weblink = \"\";\n                }\n                let toview = { \"code\": 0, \"message\": \"0\", \"ttl\": 1, \"data\": { \"count\": ids.length, \"list\": ids } };\n                let oid = ids[0].aid; // 保存当前aid以判断切p\n                debug(\"收藏列表\", toview);\n                toast.success(\"重构成功!刷新播放器...\");\n                window.BilibiliPlayer({ \"aid\": ids[0].aid, \"cid\": ids[0].cid, \"watchlater\": encodeURIComponent(JSON.stringify(toview)) });\n                API.runWhile(() => document.getElementsByClassName(\"bpui-button-text\")[1], () => document.getElementsByClassName(\"bpui-button-text\")[1].firstChild.innerText = \"收藏列表\");\n                API.switchVideo(() => {\n                    if (!API.aid)\n                        API.aid = window.aid || API.aid;\n                    if (oid && oid != window.aid) {\n                        API.aid = window.aid || API.aid;\n                        toast(\"刷新页面信息...\");\n                        history.replaceState(null, \"\", \"https://www.bilibili.com/video/av\" + API.aid + location.search + location.hash);\n                        for (let i = 0; i < ids.length; i++)\n                            if (ids[i].aid == API.aid)\n                                data = ids[i];\n                        let video_info = document.getElementById(\"viewbox_report\");\n                        let up_info = document.getElementById(\"v_upinfo\");\n                        let arc_toolbar_report = document.getElementById(\"arc_toolbar_report\");\n                        document.title = data.title;\n                        video_info.innerHTML = '<h1 title=\"' + data.title + '\"><!----><span>' + data.title + '</span></h1>' +\n                            '<div class=\"tm-info tminfo\"><span class=\"crumb\"><a href=\"//www.bilibili.com\">主页</a> &gt;</span> <span class=\"crumb\"><a href=\"//www.bilibili.com/v/douga/\">动画</a> &gt;</span> <span class=\"crumb\"><a href=\"//www.bilibili.com/v/douga/mad/\">MAD·AMV</a></span><time>' + API.timeFormat(data.pubdate * 1000, true) + '</time><a class=\"btn-appeal\">稿件投诉</a></div>' +\n                            '<div class=\"number\"><span title=\"总播放数' + data.stat.view + '\" class=\"v play\">' + API.unitFormat(data.stat.view) + '</span><span title=\"总弹幕数' + data.stat.danmaku + '\" class=\"v dm\">' + API.unitFormat(data.stat.danmaku) + '</span><span title=\"本日日排行数据过期后,再纳入本稿件的历史排行数据进行对比得出\" class=\"v rank\">最高全站日排行' + data.stat.like + '名</span><span class=\"line\"></span><span class=\"u like\" style=\"margin-right : 5px;\" title=\"点赞人数' + data.stat.his_rank + '\"><i class=\"l-icon-move\" style=\"width : 22px;height : 22px;background-position : -660px -2068px;\"></i><b class=\"l-icon-moved\" style=\"width : 22px;height : 22px;background-position : -725px -2068px;display : none;\"></b> 点赞 ' + API.unitFormat(data.stat.like) + '</span><span report-id=\"coinbtn1\" title=\"投硬币枚数' + data.stat.coin + '\" class=\"u coin\"><i class=\"c-icon-move\"></i><b class=\"c-icon-moved\" style=\"background-position: -2340px -60px; display: none;\"></b> 硬币 ' + API.unitFormat(data.stat.coin) + '</span> <span report-id=\"collect1\" title=\"收藏人数' + data.stat.favorite + '\" class=\"u fav\"><i class=\"f-icon-move\" style=\"background-position: 0px 0px;\"></i><b class=\"f-icon-moved\" style=\"background-position: -1740px -60px; display: none;\"></b> 收藏 ' + API.unitFormat(data.stat.favorite) + '</span></div>';\n                        up_info.innerHTML = '<div class=\"u-face fl\"><!----><a href=\"//space.bilibili.com/' + data.owner.mid + '\" target=\"_blank\" report-id=\"head\" class=\"a\"><img src=\"' + data.owner.face + '@68w_68h.webp\" width=\"68\" height=\"68\" class=\"up-face\" /><!----><!----><i title=\"企业/团体认证\" class=\"auth o-auth\"></i></a></div>' +\n                            '<div class=\"info\"><div class=\"user clearfix\"><a href=\"//space.bilibili.com/' + data.owner.mid + '\" target=\"_blank\" report-id=\"name\" class=\"name is-vip\">' + data.owner.name + '</a><a href=\"//message.bilibili.com/#whisper/mid' + data.owner.mid + '\" target=\"_blank\" report-id=\"message\" class=\"message icon\">发消息</a></div><div class=\"sign static\"><span>up主简介</span><!----></div><div class=\"number clearfix\"><span title=\"投稿数--\">投稿:--</span><span title=\"粉丝数--\">粉丝:--</span></div><div class=\"btn followe\"><a report-id=\"follow1\" class=\"bi-btn b-gz\"><span class=\"gz\">+ 关注</span><span class=\"ygz\">已关注</span><span class=\"qxgz\">取消关注</span></a><a report-id=\"charge\" class=\"bi-btn b-cd elecrank-btn\"><span class=\"cd\">充电</span><span class=\"wtcd\">为TA充电</span></a></div></div>';\n                        arc_toolbar_report.children[0].children[0].title = \"分享人数\" + data.stat.share;\n                        arc_toolbar_report.children[0].children[0].innerHTML = '<span class=\"t\">分享</span><span class=\"num\">' + API.unitFormat(data.stat.share) + '</span><i class=\"icon\"></i>';\n                        arc_toolbar_report.children[2].title = \"收藏人数\" + data.stat.favorite;\n                        arc_toolbar_report.children[2].innerHTML = '<div class=\"btn-item\"><i class=\"icon-move f-icon-moved\" style=\"display: none;\"></i><b class=\"icon-move f-icon-move\"></b><span class=\"t\">收藏</span><span class=\"num\">' + API.unitFormat(data.stat.favorite) + '</span></div>';\n                        arc_toolbar_report.children[3].title = \"投硬币枚数\" + data.stat.coin;\n                        arc_toolbar_report.children[3].innerHTML = '<div class=\"btn-item\"><i class=\"icon-move c-icon-moved\" style=\"display: none;\"></i><b class=\"icon-move c-icon-move\"></b><span class=\"t\">硬币</span><span class=\"num\">' + API.unitFormat(data.stat.coin) + '</span></div>';\n                        document.getElementById(\"v_tag\").children[0].setAttribute(\"hidden\", \"hidden\");\n                        document.getElementById(\"v_desc\").children[1].innerText = data.desc;\n                        new window.bbComment(\".comment\", window.aid, 1, window.UserStatus.userInfo, \"\");\n                        data.stat.like ? video_info.children[2].children[2].setAttribute(\"style\", \"display: inline-block;\") : video_info.children[2].children[2].setAttribute(\"style\", \"display: none;\");\n                        API.runWhile(() => document.getElementsByClassName(\"bpui-button-text\")[1], () => document.getElementsByClassName(\"bpui-button-text\")[1].firstChild.innerText = \"收藏列表\");\n                    }\n                });\n            });\n        });\n    }\n    catch (e) {\n        toast.error(\"mediaList.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/av/mediaList.js";
    modules["upList.js"] = "/**\n * 本模块负责生成和作视频的UP列表\n * 请以`staff`的名义传入UP主列表\n */\n(function () {\n    API.runWhile(() => document.querySelector(\"#v_upinfo\"), () => {\n        try {\n            let fl = '<span class=\"title\">UP主列表</span><div class=\"up-card-box\">';\n            // @ts-ignore:该变量由主模块传入\n            fl = staff.reduce((s, d) => {\n                s = s + `<div class=\"up-card\">\n                <a href=\"//space.bilibili.com/${d.mid}\" data-usercard-mid=\"${d.mid}\" target=\"_blank\" class=\"avatar\">\n                <img src=\"${d.face}@48w_48h.webp\" /><!---->\n                <span class=\"info-tag\">${d.title}</span><!----></a>\n                <div class=\"avatar\">\n                <a href=\"//space.bilibili.com/${d.mid}\" data-usercard-mid=\"${d.mid}\" target=\"_blank\" class=\"${(d.vip && d.vip.status) ? 'name-text is-vip' : 'name-text'}\">${d.name}</a>\n                </div></div>`;\n                return s;\n            }, fl) + `</div>`;\n            document.querySelector(\"#v_upinfo\").innerHTML = fl;\n            API.addCss(API.getModule(\"upList.css\"));\n        }\n        catch (e) {\n            toast.error(\"upList.js\", e);\n        }\n    });\n})();\n\n//# sourceURL=API://@bilibili/dist/match/av/upList.js";
    modules["videoSort.js"] = "/**\n * 本模块负责视频标题下失效的分区信息\n * 分区信息表videoSort.json可能需要长期维护\n */\n(function () {\n    API.runWhile(() => document.querySelector(\".tm-info\"), () => {\n        try {\n            const sort = API.getModule(\"videoSort.json\");\n            if (API.path.name == \"av\" && API.tid && API.tid in sort) {\n                const nodes = document.querySelector(\".tm-info\").childNodes;\n                nodes[1].replaceWith(nodes[0].cloneNode(true));\n                nodes[2].replaceWith(nodes[0].cloneNode(true));\n                nodes[2].childNodes[1].remove();\n                nodes[1].childNodes[0].href = sort[sort[API.tid][0]][2];\n                nodes[1].childNodes[0].text = sort[sort[API.tid][0]][1];\n                nodes[2].childNodes[0].href = sort[API.tid][2];\n                nodes[2].childNodes[0].text = sort[API.tid][1];\n            }\n            else if (API.path.name == \"watchlater\") {\n                const nodes = document.querySelector(\".tm-info\").childNodes;\n                if (nodes[2].nodeType === 8) {\n                    xhr({\n                        url: `https://api.bilibili.com/x/web-interface/view?aid=${API.aid}`,\n                        responseType: \"json\"\n                    }).then(d => {\n                        API.tid = API.jsonCheck(d).data.tid;\n                        if (API.tid && API.tid in sort) {\n                            nodes[2].replaceWith(nodes[0].cloneNode(true));\n                            nodes[4].replaceWith(nodes[0].cloneNode(true));\n                            nodes[4].childNodes[1].remove();\n                            nodes[2].childNodes[0].href = sort[sort[API.tid][0]][2];\n                            nodes[2].childNodes[0].text = sort[sort[API.tid][0]][1];\n                            nodes[4].childNodes[0].href = sort[API.tid][2];\n                            nodes[4].childNodes[0].text = sort[API.tid][1];\n                        }\n                    });\n                }\n            }\n        }\n        catch (e) {\n            debug.error(\"videoSort.js\", e);\n        }\n    });\n})();\n\n//# sourceURL=API://@bilibili/dist/match/av/videoSort.js";
    modules["bangumi.js"] = "/**\n * 本模块负责重写旧版bangumi页面\n */\n(function () {\n    try {\n        class Bangumi {\n            constructor() {\n                this.epid = API.path[5].startsWith('ep') ? location.href.match(/[0-9]+/)[0] : null;\n                this.obj = {};\n                this.isBANGUMI__INITIAL_STATE__ = (pet) => true;\n                API.path.name = \"bangumi\";\n                API.path[5].startsWith('ss') && Reflect.set(this.obj, \"season_id\", location.href.match(/[0-9]+/)[0]);\n                API.path[5].startsWith('ep') && Reflect.set(this.obj, \"ep_id\", location.href.match(/[0-9]+/)[0]);\n                config.rewriteMethod == \"异步\" ? this.prepareA() : this.prepareB();\n            }\n            async prepareA() {\n                if (API.uid && !this.epid) {\n                    const data = await xhr({ url: location.href });\n                    const arr = data.match(/last_ep_id\\\"\\:[0-9]+/) || [];\n                    this.epid = (arr[0] && arr[0].split(\":\")[1]) || null;\n                }\n                await new Promise(r => {\n                    // 准备__INITIAL_STATE__\n                    if (Reflect.has(this.obj, \"season_id\") || Reflect.has(this.obj, \"ep_id\")) {\n                        xhr({\n                            url: API.objUrl(\"https://bangumi.bilibili.com/view/web_api/season\", this.obj),\n                            responseType: \"json\",\n                            credentials: true\n                        }).then(d => {\n                            API.importModule(\"bangumi-season.js\", { __INITIAL_STATE__: d, epid: this.epid }, true);\n                            r(true);\n                        }).catch(e => {\n                            toast.error(\"获取bangumi数据出错!\", e);\n                            config.videoLimit && xhr({\n                                url: API.objUrl(`${config.limitServer || \"https://api.global.bilibili.com\"}/intl/gateway/v2/ogv/view/app/season`, this.obj),\n                                responseType: \"json\",\n                                credentials: true\n                            }).then(d => {\n                                API.importModule(\"bangumi-global.js\", { __INITIAL_STATE__: d, epid: this.epid }, true);\n                                r(true);\n                                API.limit = true;\n                                API.globalLimit = true;\n                            }).catch(e => { debug.error(e); API.importModule(\"vector.js\"); });\n                        });\n                    }\n                });\n                this.write();\n            }\n            prepareB() {\n                if (API.uid && !this.epid) {\n                    const data = xhr({ url: location.href, async: false });\n                    const arr = data.match(/last_ep_id\\\"\\:[0-9]+/) || [];\n                    this.epid = (arr[0] && arr[0].split(\":\")[1]) || null;\n                }\n                let d = xhr({\n                    url: API.objUrl(\"https://bangumi.bilibili.com/view/web_api/season\", this.obj),\n                    async: false,\n                    credentials: true\n                });\n                try {\n                    API.importModule(\"bangumi-season.js\", { __INITIAL_STATE__: d, epid: this.epid }, true);\n                }\n                catch (e) {\n                    toast.error(\"获取bangumi数据出错!\", e);\n                    if (!config.videoLimit)\n                        return;\n                    d = xhr({\n                        url: API.objUrl(`${config.limitServer || \"https://api.global.bilibili.com\"}/intl/gateway/v2/ogv/view/app/season`, this.obj),\n                        async: false\n                    });\n                    API.importModule(\"bangumi-global.js\", { __INITIAL_STATE__: d, epid: this.epid }, true);\n                    API.limit = true;\n                    API.globalLimit = true;\n                }\n                this.write();\n            }\n            write() {\n                var _a, _b, _c;\n                if (this.isBANGUMI__INITIAL_STATE__(API.__INITIAL_STATE__)) {\n                    if (((_b = (_a = API.__INITIAL_STATE__) === null || _a === void 0 ? void 0 : _a.epInfo) === null || _b === void 0 ? void 0 : _b.badge) === \"互动\")\n                        return (delete API.path.name, toast.warning(\"这似乎是个互动番剧!\", \"什么!番剧也能互动?\", \"可惜旧版播放器不支持 ಥ_ಥ\"), API.importModule(\"vector.js\"));\n                    // 备份还原旧版播放器设置数据\n                    API.restorePlayerSetting();\n                    API.scriptIntercept([\"video-nano\"]); // 新版播放器拦截\n                    API.scriptIntercept([\"stardust-video\"]); // 新版播放器拦截\n                    config.bangumiEplist && ((_c = API.__INITIAL_STATE__) === null || _c === void 0 ? void 0 : _c.epList[1]) && (API.__INITIAL_STATE__.special = false, API.__INITIAL_STATE__.mediaInfo.bkg_cover = undefined);\n                    window.__INITIAL_STATE__ = API.__INITIAL_STATE__;\n                    API.__INITIAL_STATE__.special ? API.rewriteHTML(API.getModule(\"bangumi-special.html\").replace(\"static.hdslb.com/js/video.min.js\", \"cdn.jsdelivr.net/gh/MotooriKashin/Bilibili-Old/dist/video.min.js\")) : API.rewriteHTML(API.getModule(\"bangumi.html\").replace(\"static.hdslb.com/js/video.min.js\", \"cdn.jsdelivr.net/gh/MotooriKashin/Bilibili-Old/dist/video.min.js\"));\n                    document.title = API.__INITIAL_STATE__.mediaInfo.title + \"_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili\";\n                    // 分集数据\n                    config.episodeData && API.importModule(\"episodeData.js\");\n                    // 移除过期节点\n                    API.runWhile(() => document.querySelector(\".new-entry\"), () => { var _a; return (_a = document.querySelector(\".new-entry\")) === null || _a === void 0 ? void 0 : _a.remove(); });\n                    // 修复数据\n                    API.importModule(\"restoreData.js\");\n                    // 媒体控制\n                    let getPlaylistIndex = () => API.__INITIAL_STATE__.epList.findIndex(v => v.cid == (window.cid || API.cid));\n                    Object.defineProperty(window, \"pageno\", { get: () => getPlaylistIndex() + 1 });\n                    API.importModule(\"mediaControl.js\", {\n                        getPlaylistIndex: () => getPlaylistIndex(),\n                        mediaInfo: (pid) => {\n                            if (this.isBANGUMI__INITIAL_STATE__(API.__INITIAL_STATE__))\n                                return {\n                                    title: API.__INITIAL_STATE__.mediaInfo.title,\n                                    artist: API.__INITIAL_STATE__.mediaInfo.jp_title,\n                                    chapterName: API.__INITIAL_STATE__.epList[pid].index_title,\n                                    coverUrl: [{ src: API.__INITIAL_STATE__.epList[pid].cover, sizes: \"960x600\" }]\n                                };\n                        }\n                    });\n                }\n            }\n        }\n        new Bangumi();\n    }\n    catch (e) {\n        toast.error(\"bangumi.js\", e);\n        API.importModule(\"vector.js\");\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/bangumi/bangumi.js";
    modules["episodeData.js"] = "/**\n * 本模块负责添加bangumi分集数据\n */\n(function () {\n    try {\n        let first = 0; // 首p指示\n        API.switchVideo(async () => {\n            try {\n                first++;\n                let views = document.querySelector(\".view-count\").querySelector(\"span\");\n                let danmakus = document.querySelector(\".danmu-count\").querySelector(\"span\");\n                if (first === 1) {\n                    // 首p时辈分总播放数和总弹幕数\n                    views.setAttribute(\"title\", \"总播放数 \" + views.innerText);\n                    danmakus.setAttribute(\"title\", \"总弹幕数 \" + danmakus.innerText);\n                    debug.debug(\"总播放数\", views.innerText, \" 总弹幕数\", danmakus.innerText);\n                }\n                let data = await xhr({\n                    url: API.objUrl(\"https://api.bilibili.com/x/web-interface/archive/stat\", { \"aid\": String(API.aid) }),\n                    credentials: true\n                }); // 获取分集数据\n                data = API.jsonCheck(data).data;\n                let view = data.view;\n                let danmaku = data.danmaku;\n                view = API.unitFormat(view);\n                danmaku = API.unitFormat(danmaku);\n                views.innerText = view;\n                danmakus.innerText = danmaku;\n                debug.debug(\"播放\", view + \" 弹幕\", danmaku);\n            }\n            catch (e) {\n                debug.error(\"episodeData.js\", e);\n            }\n        });\n    }\n    catch (e) {\n        debug.error(\"episodeData.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/bangumi/episodeData.js";
    modules["restoreData.js"] = "/**\n * 本模块负责修复Bangumi页面数据错误\n */\n(function () {\n    try {\n        // 修复追番数\n        API.xhrhook([\"bangumi.bilibili.com/ext/web_api/season_count?\"], function (args) {\n            this.addEventListener('readystatechange', () => {\n                if (this.readyState === 4) {\n                    try {\n                        let response = API.jsonCheck(this.responseText);\n                        response.result.favorites = response.result.follow;\n                        Object.defineProperty(this, 'response', { writable: true });\n                        Object.defineProperty(this, 'responseText', { writable: true });\n                        this.response = this.responseText = JSON.stringify(response);\n                    }\n                    catch (e) {\n                        debug.error(\"restoreData.js\", e);\n                    }\n                }\n            });\n            args[1] = args[1].replace('bangumi.bilibili.com/ext/web_api/season_count', 'api.bilibili.com/pgc/web/season/stat');\n        });\n        // 修复片尾番剧推荐\n        API.xhrhook([\"api.bilibili.com/pgc/web/recommend/related/recommend\"], function (args) {\n            this.addEventListener('readystatechange', () => {\n                if (this.readyState === 4) {\n                    try {\n                        let response = API.jsonCheck(this.responseText);\n                        if (response.result && response.result.season)\n                            response.result = response.result.season;\n                        Object.defineProperty(this, 'response', { writable: true });\n                        Object.defineProperty(this, 'responseText', { writable: true });\n                        this.response = this.responseText = JSON.stringify(response);\n                    }\n                    catch (e) {\n                        debug.error(\"restoreData.js\", e);\n                    }\n                }\n            });\n        });\n        // 修复番剧推荐\n        API.xhrhook([\"comment.bilibili.com/playtag\"], function (args) {\n            args[1] = \"https://comment.bilibili.com/playtag,2-2?html5=1\";\n            restoreBangumiRecommand();\n        });\n        API.addCss(`#bangumi_recommend_vertial .recom-list{\n            height: 960px;\n            overflow: auto;\n        } .recom-list::-webkit-scrollbar {\n            width: 0 !important;\n            height: 0 !important;\n        }`, \"recom-list\");\n        async function restoreBangumiRecommand() {\n            let data = API.jsonCheck(await xhr({ url: API.objUrl(\"https://api.bilibili.com/pgc/web/recommend/related/recommend\", { season_id: String(API.__INITIAL_STATE__.ssId) }) })).result;\n            let result = API.jsonCheck(await xhr({ url: API.objUrl(\"https://api.bilibili.com/x/tag/info\", { tag_name: API.__INITIAL_STATE__.mediaInfo.title }) }));\n            result = API.jsonCheck(await xhr({ url: API.objUrl(\"https://api.bilibili.com/x/web-interface/tag/top\", { tid: result.data.tag_id }) })).data;\n            if (!document.querySelector(\".bilibili-player-recommend\")) {\n                await new Promise(r => {\n                    API.runWhile(() => document.querySelector(\".bilibili-player-recommend\"), r);\n                });\n            }\n            result = result.reduce((s, d) => {\n                s = s + `<li class=\"recom-item\">\n                <a href=\"https://www.bilibili.com/video/av${d.aid}\" target=\"_blank\" title=\"${d.title}\">\n                <div class=\"recom-img\"><div class=\"common-lazy-img\">\n                <img alt=\"${d.title}\" src=\"${d.pic.replace(\"http:\", \"\")}@224w_140h.webp\" lazy=\"loaded\">\n                </div></div>\n                <div class=\"recom-info\">\n                <div class=\"info-title\">${d.title}</div>\n                <div class=\"info-count\">\n                <div class=\"play-count\"><i></i><span>${API.unitFormat(d.stat.view)}</span></div>\n                <div class=\"danmu-count\"><i></i><span>${API.unitFormat(d.stat.danmaku)}</span></div>\n                </div></div></a></li>`;\n                return s;\n            }, \"\");\n            // @ts-ignore:节点肯定存在\n            document.querySelector(\".recom-list.clearfix\").innerHTML = result;\n            data = data.reduce((s, d) => {\n                s = s + `<a class=\"bilibili-player-recommend-video\" href=\"${d.url}\" target=\"_blank\">\n                <div class=\"bilibili-player-recommend-left\">\n                <img src=\"${d.new_ep.cover || d.cover}@160w_100h.webp\" alt=\"${d.title}\" class=\"mCS_img_loaded\" />\n                <span class=\"player-tooltips-trigger\"><i class=\"bilibili-player-iconfont icon-22wait-normal\"></i></span>\n                </div>\n                <div class=\"bilibili-player-recommend-right\">\n                <div class=\"bilibili-player-recommend-title\" title=\"${d.title}\">${d.title}</div>\n                <div class=\"bilibili-player-recommend-click\"><i class=\"bilibili-player-iconfont icon-12iconplayed\"></i>${API.unitFormat(d.stat.view)}</div>\n                <div class=\"bilibili-player-recommend-danmaku\"><i class=\"bilibili-player-iconfont icon-12icondanmu\"></i>${API.unitFormat(d.stat.danmaku)}</div>\n                </div></a>`;\n                return s;\n            }, '');\n            let item = document.querySelector(\".bilibili-player-recommend\");\n            if (!item.querySelector(\".mCSB_container\")) {\n                await new Promise(r => {\n                    API.runWhile(() => item.querySelector(\".mCSB_container\"), r, 500, 0);\n                });\n            }\n            // @ts-ignorei:前面判定了存在节点\n            item.querySelector(\".mCSB_container\").innerHTML = data;\n        }\n    }\n    catch (e) {\n        toast.error(\"restoreData.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/bangumi/restoreData.js";
    modules["ad2info.js"] = "/**\n * 本模块负责将主页失效的广告区转化为资讯区\n */\n(function () {\n    try {\n        API.runWhile(() => document.querySelector(\"#bili_ad\"), function () {\n            const node = document.querySelector(\"#bili_ad\");\n            const sight = node.querySelectorAll(\"a\");\n            const title = node.querySelector(\".name\");\n            const technology = document.querySelector(\"#bili_technology\").querySelector(\".name\");\n            const digital = document.querySelector(\"#bili_digital\").querySelector(\".name\");\n            title && (title.innerText = \"资讯\");\n            sight.forEach(d => {\n                d.href && d.href.includes(\"www.bilibili.com/v/ad/ad/\") && (d.href = \"https://www.bilibili.com/v/information/\");\n            });\n            API.addElement(\"div\", { class: \"r-con\" }, undefined, '<div class=\"r-con\"><header style=\"margin-bottom: 14px\"><h3 style=\"font-size: 18px;font-weight: 400;\">资讯分区正式上线啦!</h3></header><div class=\"carousel-module\"><div class=\"panel\"><a href=\"https://www.bilibili.com/v/information\" target=\"_blank\"><img src=\"//i0.hdslb.com/bfs/archive/0747d26dbbc3bbf087d47cff49e598a326b0030c.jpg@320w_330h_1c.webp\" width=\"260\" height=\"280\"/></a></div></div></div>', undefined, document.querySelector(\"#ranking_ad\"));\n            technology.href = \"//www.bilibili.com/v/knowledge/\";\n            technology.innerHTML = \"知识\";\n            digital.href = \"//www.bilibili.com/v/tech/\";\n            digital.innerHTML = \"科技\";\n            document.querySelector(\".icon.icon_t.icon-ad\").setAttribute(\"style\", \"background-image: url(//cdn.jsdelivr.net/gh/MotooriKashin/Bilibili-Old/image/news.png);background-position: unset;\");\n        });\n        API.runWhile(() => document.querySelector(\".report-wrap-module.elevator-module\"), function () {\n            const node = document.querySelector(\".report-wrap-module.elevator-module\");\n            for (let item of node.children[1].children) {\n                if (item.innerHTML == \"广告\")\n                    item.innerHTML = \"资讯\";\n                if (item.innerHTML == \"科技\")\n                    item.innerHTML = \"知识\";\n                if (item.innerHTML == \"数码\")\n                    item.innerHTML = \"科技\";\n            }\n        });\n    }\n    catch (e) {\n        toast.error(\"ad2info.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/index/ad2info.js";
    modules["biliIndexRec.js"] = "/**\n * 本模块负责修复主页直播分区数据\n */\n(function () {\n    try {\n        API.xhrhook([\"api.live.bilibili.com/room/v1/RoomRecommend/biliIndexRec\"], function (args) {\n            args[1] = args[1].includes(\"List\") ? args[1].replace('api.live.bilibili.com/room/v1/RoomRecommend/biliIndexRecList', 'api.live.bilibili.com/xlive/web-interface/v1/webMain/getList?platform=web') : args[1].replace('api.live.bilibili.com/room/v1/RoomRecommend/biliIndexRecMore', 'api.live.bilibili.com/xlive/web-interface/v1/webMain/getMoreRecList?platform=web');\n            this.addEventListener('readystatechange', () => {\n                if (this.readyState === 4) {\n                    try {\n                        let response = this.responseText.replace(/preview_banner_list/, \"preview\").replace(/ranking_list/, \"ranking\").replace(/recommend_room_list/, \"recommend\");\n                        response = JSON.parse(response);\n                        response.data.text_link = { text: \"233秒居然能做这些!\", link: \"//vc.bilibili.com\" };\n                        if (response.data.recommend) {\n                            for (let i = 0; i < response.data.recommend.length; i++) {\n                                response.data.recommend[i].pic = response.data.recommend[i].cover;\n                                response.data.recommend[i].link = \"//live.bilibili.com\" + response.data.recommend[i].link;\n                            }\n                        }\n                        if (response.data.preview)\n                            for (let i = 0; i < response.data.preview.length; i++)\n                                response.data.preview[i].url = response.data.preview[i].link;\n                        Object.defineProperty(this, 'response', { writable: true });\n                        Object.defineProperty(this, 'responseText', { writable: true });\n                        this.response = this.responseText = JSON.stringify(response);\n                    }\n                    catch (e) {\n                        debug.error(\"roomRecommend.js\", e);\n                    }\n                }\n            });\n        });\n    }\n    catch (e) {\n        toast.error(\"biliIndexRec.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/index/biliIndexRec.js";
    modules["index.js"] = "/**\n * 本模块负责重写B站旧版主页\n */\n(function () {\n    try {\n        class Index {\n            constructor() {\n                API.path.name = \"index\";\n                config.rewriteMethod == \"异步\" ? this.prepareA() : this.prepareB();\n            }\n            async prepareA() {\n                const data = (await xhr({\n                    url: \"https://api.bilibili.com/x/web-show/res/locs?pf=0&ids=4694,34,31\",\n                    responseType: \"json\"\n                })).data;\n                let result = { locsData: { 23: data[4694], 34: data[34], 31: data[31] } };\n                config.indexLoc && this.reAD(result);\n                window.__INITIAL_STATE__ = result;\n                this.write();\n            }\n            prepareB() {\n                const data = API.jsonCheck(xhr({\n                    url: \"https://api.bilibili.com/x/web-show/res/locs?pf=0&ids=4694,34,31\",\n                    async: false\n                })).data;\n                let result = { locsData: { 23: data[4694], 34: data[34], 31: data[31] } };\n                config.indexLoc && this.reAD(result);\n                window.__INITIAL_STATE__ = result;\n                this.write();\n            }\n            reAD(data) {\n                for (let key in data.locsData) {\n                    if (Array.isArray(data.locsData[key])) {\n                        data.locsData[key] = data.locsData[key].filter((d) => {\n                            return d.is_ad ? (debug.debug(\"移除广告\", key, d), false) : true;\n                        });\n                    }\n                }\n            }\n            write() {\n                window.__INITIAL_STATE__ = API.__INITIAL_STATE__;\n                API.rewriteHTML(API.getModule(\"index.html\"));\n                // 移除无效节点\n                API.runWhile(() => document.querySelector(\".ver\"), () => { var _a; return (_a = document.querySelector(\".ver\")) === null || _a === void 0 ? void 0 : _a.remove(); });\n                API.runWhile(() => document.querySelector(\"#fixed_app_download\"), () => { var _a; return (_a = document.querySelector(\"#fixed_app_download\")) === null || _a === void 0 ? void 0 : _a.remove(); });\n                // 修复失效分区\n                API.importModule(\"indexSort.js\");\n            }\n        }\n        new Index();\n    }\n    catch (e) {\n        toast.error(\"index.js\", e);\n        API.importModule(\"vector.js\");\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/index/index.js";
    modules["indexRecommend.js"] = "/**\n * 本模块负责取消主页个性化推荐\n */\n(function () {\n    let indexRecommend, indexFlag;\n    API.runWhile(() => document.querySelector(\".bili-wrapper\"), async function () {\n        try {\n            let node = document.querySelector(\".recommend-module.clearfix\"); // 父节点\n            let prev = API.addElement(\"span\", { class: \"rec-btn prev\" }, node, undefined, undefined, document.querySelector(\".rec-btn.prev\")); // 替换切换按钮\n            let next = API.addElement(\"span\", { class: \"rec-btn next\" }, node, undefined, undefined, document.querySelector(\".rec-btn.next\")); // 替换切换按钮\n            prev.innerHTML = next.innerHTML = \"切换\"; // 命名按钮\n            prev.onclick = next.onclick = async () => {\n                // 按钮单击回调\n                document.querySelectorAll(\".groom-module.home-card\").forEach(d => d.remove()); // 移除现有数据\n                let wait = API.addElement(\"div\", { class: \"load-state\" }, node, undefined, true); // 添加loading临时节点\n                wait.innerHTML = '<span class=\"loading\">正在加载...</span><!----><!---->'; // 写入loading提示\n                indexRecommend = indexRecommend && indexRecommend.length > 20 ? indexRecommend : API.jsonCheck(await xhr({\n                    url: \"https://api.bilibili.com/x/web-interface/index/top/rcmd?fresh_type=3\",\n                    credentials: !config.privateRecommend\n                })).data.item; // 请求推荐数据,分情况,个性化推荐每次都请求,全站推荐只请求一次\n                indexFlag = indexRecommend.length < 20 ? 10 : indexFlag || ((API.uid && config.privateRecommend) ? 10 : 20); // 设置遍历起始点,个性化推荐固定为10\n                wait.remove(); // 移除loading节点\n                for (let i = indexFlag - 1; i >= indexFlag - 10; i--) {\n                    // 依次创建推荐数据,长度固定为10\n                    API.addElement(\"div\", { class: \"groom-module home-card\" }, node, undefined, true).innerHTML = `<a href=\"//www.bilibili.com/video/av${indexRecommend[i].aid || indexRecommend[i].id}\" target=\"_blank\" title=\"${indexRecommend[i].title}\">\n                        <img src=\"${indexRecommend[i].pic.replace(\"http:\", \"\")}@160w_100h.webp\" alt=\"${indexRecommend[i].title}\" width=\"160\" height=\"100\" class=\"pic\">\n                        \"><!----><div class=\"card-mark\"><p class=\"title\">${indexRecommend[i].title}</p><p class=\"author\">up主:${indexRecommend[i].owner.name}</p><p class=\"play\">播放:${API.unitFormat(indexRecommend[i].stat.view)}</p></div></a><div class=\"watch-later-trigger w-later\"></div></div>`;\n                }\n                indexFlag = indexRecommend.length < 20 ? 10 : indexFlag < 30 ? indexFlag + 10 : 10; // 对于全站推荐,刷新遍历起始点\n            };\n            prev.click(); // 移除个性化推荐\n        }\n        catch (e) {\n            debug.error(\"indexRecommend.js\", e);\n        }\n    });\n})();\n\n//# sourceURL=API://@bilibili/dist/match/index/indexRecommend.js";
    modules["indexSort.js"] = "/**\n * 本模块负责修复主页失效分区\n */\n(function () {\n    try {\n        API.importModule(\"biliIndexRec.js\");\n        API.importModule(\"ad2info.js\");\n        API.importModule(\"mediaRank.js\");\n        API.importModule(\"indexRecommend.js\");\n        // 广告取转资讯区\n        API.jsonphook([\"region\", \"rid=165\"], function (xhr) {\n            xhr.url = xhr.url.replace(\"rid=165\", \"rid=202\");\n        });\n        // 用户热点最新投稿修复资讯区最新投稿\n        API.jsonphook([\"newlist\", \"rid=165\"], function (xhr) {\n            xhr.url = xhr.url.replace(\"rid=165\", \"rid=203\");\n        });\n        // 取消原创排行榜\n        API.jsonphook([\"region\", \"original=1\"], function (xhr) {\n            xhr.url = xhr.url.replace(\"original=1\", \"original=0\");\n        });\n        // 修复置顶推荐\n        API.jsonphook([\"api.bilibili.com/x/web-interface/ranking/index\"], function (xhr) {\n            xhr.url = xhr.url.replace(\"ranking/index\", \"index/top\");\n        });\n    }\n    catch (e) {\n        toast.error(\"indexSort.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/index/indexSort.js";
    modules["mediaRank.js"] = "/**\n * 本模块负责将主页电影、电视剧、纪录片排行转化为番剧样式\n */\n(function () {\n    try {\n        async function fixRank(node) {\n            const sorts = {\n                bili_movie: [\"ranking_movie\", 2, \"https://www.bilibili.com/ranking/cinema/23/0/3\"],\n                bili_teleplay: [\"ranking_teleplay\", 5, \"https://www.bilibili.com/ranking/cinema/11/0/3\"],\n                bili_documentary: [\"ranking_documentary\", 3, \"https://www.bilibili.com/ranking/cinema/177/0/3\"]\n            };\n            const sort = sorts[node.id];\n            if (!sort)\n                return;\n            let section = node.getElementsByClassName(\"sec-rank report-wrap-module zone-rank\")[0];\n            section.innerHTML = '<header class=\"rank-head\"><h3>排行</h3></header><div class=\"rank-list-wrap\"><ul class=\"bangumi-rank-list rank-list\"></ul></div><a href=\"' + sort[2] + '\" target=\"_blank\" class=\"more-link\">查看更多<i class=\"icon icon-arrow-r\"></i></a>';\n            try {\n                let data = await xhr({ url: API.objUrl(\"https://api.bilibili.com/pgc/season/rank/web/list\", { season_type: sort[1], day: '3' }) });\n                data = API.jsonCheck(data).data;\n                let div = node.getElementsByClassName(\"bangumi-rank-list rank-list\")[0];\n                for (let i = 0; i < 8; i++) {\n                    let li = document.createElement(\"li\"), cl = i < 3 ? \"rank-item highlight\" : \"rank-item\", fw;\n                    li.setAttribute(\"class\", cl);\n                    li.innerHTML = '<i class=\"ri-num\">' + (i + 1) + '</i><a href=\"' + data.list[i].url + '\" target=\"_blank\" title=\"' + data.list[i].title + ' 播放:' + data.list[i].stat.view + '\" class=\"ri-info-wrap\"><p class=\"ri-title\">' + data.list[i].title + '</p><span class=\"ri-total\">' + data.list[i].new_ep.index_show + '</span></a>';\n                    li.onmouseover = () => {\n                        fw = document.createElement(\"div\");\n                        fw.setAttribute(\"class\", \"bangumi-info-module\");\n                        fw.setAttribute(\"style\", 'left: ' + li.getBoundingClientRect().left + 'px; top: ' + (API.getTotalTop(li) - 150) + 'px;');\n                        fw.innerHTML = '<div class=\"v-preview clearfix\"><div class=\"lazy-img cover\"><img alt=\"' + data.list[i].title + '\" src=\"' + data.list[i].cover + '\" /></div><div><p class=\"title\">' + data.list[i].title + '</p><p class=\"desc\">' + data.list[i].new_ep.index_show + '</p></div></div><div class=\"v-data\"><span class=\"play\"><i class=\"icon\"></i>' + API.unitFormat(data.list[i].stat.view) + '</span><span class=\"danmu\"><i class=\"icon\"></i>' + API.unitFormat(data.list[i].stat.danmaku) + '</span><span class=\"fav\"><i class=\"icon\"></i>' + API.unitFormat(data.list[i].stat.follow) + '</span></div>';\n                        document.body.appendChild(fw);\n                    };\n                    li.onmouseout = () => fw.remove();\n                    div.appendChild(li);\n                }\n            }\n            catch (e) {\n                debug.error(\"indexSort.js\", e);\n            }\n        }\n        API.runWhile(() => document.querySelector(\"#bili_movie\"), () => fixRank(document.querySelector(\"#bili_movie\")));\n        API.runWhile(() => document.querySelector(\"#bili_teleplay\"), () => fixRank(document.querySelector(\"#bili_teleplay\")));\n        API.runWhile(() => document.querySelector(\"#bili_documentary\"), () => fixRank(document.querySelector(\"#bili_documentary\")));\n    }\n    catch (e) {\n        toast.error(\"mediaRank.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/index/mediaRank.js";
    modules["live.js"] = "/**\n * 本模块负责引导直播相关模块\n */\n(function () {\n    try {\n        config.liveStream && API.importModule(\"liveStream.js\");\n        config.liveP2p && API.importModule(\"WebRTC.js\");\n        config.sleepCheck && API.importModule(\"sleepCheck.js\");\n        config.anchor && API.runWhile(() => document.querySelector(\"anchor-guest-box-id\"), () => { var _a; return (_a = document.querySelector(\"anchor-guest-box-id\")) === null || _a === void 0 ? void 0 : _a.remove(); }, 500, 0);\n        config.pkvm && API.runWhile(() => document.querySelector(\"chaos-pk-vm\"), () => { var _a; return (_a = document.querySelector(\"chaos-pk-vm\")) === null || _a === void 0 ? void 0 : _a.remove(); }, 500, 0);\n        API.runWhile(() => document.querySelector(\".web-player-icon-roomStatus\"), () => { var _a; return (_a = document.querySelector(\".web-player-icon-roomStatus\")) === null || _a === void 0 ? void 0 : _a.remove(); });\n    }\n    catch (e) {\n        toast.error(\"live.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/live/live.js";
    modules["liveStream.js"] = "/**\n * 本模块负责拦截直播间流媒体\n */\n(function () {\n    try {\n        Object.defineProperty(window, \"__NEPTUNE_IS_MY_WAIFU__\", { get: () => undefined, set: () => true });\n        API.xhrhook([\"api.live.bilibili.com/xlive/web-room/v2/index/getRoomPlayInfo\"], function (args) {\n            this.addEventListener('readystatechange', () => {\n                if (this.readyState === 4) {\n                    try {\n                        let response = API.jsonCheck(this.responseText);\n                        response.data.live_time = -1;\n                        response.data.playurl_info = null;\n                        if (response.data) {\n                            response.data.live_status = 0;\n                        }\n                        toast.warning(\"已拦截直播流,可在设置中解除限制!\");\n                        Object.defineProperty(this, 'response', { writable: true });\n                        Object.defineProperty(this, 'responseText', { writable: true });\n                        this.response = this.responseText = JSON.stringify(response);\n                    }\n                    catch (e) {\n                        debug.error(\"liveStream.js\", e);\n                    }\n                }\n            });\n        });\n    }\n    catch (e) {\n        toast.error(\"liveStream.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/live/liveStream.js";
    modules["sleepCheck.js"] = "/**\n * 本模块负责禁用直播间挂机检测\n */\n(function () {\n    try {\n        const fun = setInterval;\n        let flag = 0;\n        window.setInterval = (...args) => {\n            if (args[1] && args[1] == 300000 && args[0] && args[0].toString() == \"function(){e.triggerSleepCallback()}\") {\n                if (!flag) {\n                    toast.warning(\"成功阻止直播间挂机检测!\");\n                    flag++;\n                }\n                return Number.MIN_VALUE;\n            }\n            return fun.call(window, ...args);\n        };\n    }\n    catch (e) {\n        toast.error(\"sleepCheck.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/live/sleepCheck.js";
    modules["WebRTC.js"] = "/**\n * 本模块负责禁用WebRTC以禁止直播间p2p共享\n * 代码参看了WebRTC Control的源码,非常感谢!\n * @see WebRTC-Control {@link https://mybrowseraddon.com/webrtc-control.html}\n */\n// @ts-nocheck\ntry {\n    if (typeof navigator.getUserMedia !== \"undefined\")\n        navigator.getUserMedia = undefined;\n    if (typeof window.MediaStreamTrack !== \"undefined\")\n        window.MediaStreamTrack = undefined;\n    if (typeof window.RTCPeerConnection !== \"undefined\")\n        window.RTCPeerConnection = undefined;\n    if (typeof window.RTCSessionDescription !== \"undefined\")\n        window.RTCSessionDescription = undefined;\n    if (typeof navigator.mozGetUserMedia !== \"undefined\")\n        navigator.mozGetUserMedia = undefined;\n    if (typeof window.mozMediaStreamTrack !== \"undefined\")\n        window.mozMediaStreamTrack = undefined;\n    if (typeof window.mozRTCPeerConnection !== \"undefined\")\n        window.mozRTCPeerConnection = undefined;\n    if (typeof window.mozRTCSessionDescription !== \"undefined\")\n        window.mozRTCSessionDescription = undefined;\n    if (typeof navigator.webkitGetUserMedia !== \"undefined\")\n        navigator.webkitGetUserMedia = undefined;\n    if (typeof window.webkitMediaStreamTrack !== \"undefined\")\n        window.webkitMediaStreamTrack = undefined;\n    if (typeof window.webkitRTCPeerConnection !== \"undefined\")\n        window.webkitRTCPeerConnection = undefined;\n    if (typeof window.webkitRTCSessionDescription !== \"undefined\")\n        window.webkitRTCSessionDescription = undefined;\n    toast.warning(\"禁用直播间P2P上传!\");\n}\ncatch (e) {\n    API.trace(e, \"WebRTC.js\", true);\n}\n\n//# sourceURL=API://@bilibili/dist/match/live/WebRTC.js";
    modules["album.js"] = "/**\n * 本模块负责将空间中相簿的链接从动态重定向回去\n */\n(function () {\n    try {\n        API.xhrhook([\"api.bilibili.com/x/dynamic/feed/draw/doc_list\"], function (args) {\n            this.addEventListener('readystatechange', () => {\n                if (this.readyState === 4) {\n                    let response = JSON.parse(this.responseText);\n                    let data = response.data.items.reduce((s, d) => {\n                        s.push(d.doc_id);\n                        return s;\n                    }, []);\n                    setTimeout(() => {\n                        document.querySelectorAll(\".album-card\").forEach((d, i) => {\n                            d.firstChild.href = `//h.bilibili.com/${data[i]}`;\n                            d.children[1].href = `//h.bilibili.com/${data[i]}`;\n                        });\n                    }, 1000);\n                }\n            });\n        });\n    }\n    catch (e) {\n        debug.error(\"album.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/space/album.js";
    modules["jointime.js"] = "/**\n * 本模块负责添加空间账号注册时间信息\n */\n(async function () {\n    try {\n        if (!document.querySelector(\".user-info-title\")) {\n            await new Promise(r => {\n                API.runWhile(() => document.querySelector(\".user-info-title\"), r);\n            });\n        }\n        let data = API.jsonCheck(await xhr.GM({ url: API.objUrl(\"https://account.bilibili.com/api/member/getCardByMid\", { \"mid\": API.mid }) }));\n        let jointime = API.timeFormat(data.card.regtime * 1000, true);\n        let node = document.querySelector(\".user-info-title\");\n        API.addElement(\"span\", { class: \"info-jointime\" }, node, jointime);\n    }\n    catch (e) {\n        toast.error(\"jsontime.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/space/jointime.js";
    modules["lostVideo.js"] = "/**\n * 本模块负责获取收藏、频道中的失效视频信息\n */\n(function () {\n    try {\n        async function getLostVideo(aid) {\n            let result = []; // 失效视频信息缓存\n            try { // 尝试访问Biliplus\n                let data = await xhr.GM({ url: `https://www.biliplus.com/video/av${aid}` });\n                if (data.match(/\\<title\\>.+?\\ \\-\\ AV/)) {\n                    result[0] = data.match(/\\<title\\>.+?\\ \\-\\ AV/)[0].replace(/<title>/, \"\").replace(/ - AV/, \"\");\n                    result[1] = data.match(/\\<img style=\\\"display:none\\\"\\ src=\\\".+?\\\"\\ alt/)[0].replace(/<img style=\"display:none\" src=\"/, \"\").replace(/\" alt/, \"\");\n                }\n            }\n            catch (e) {\n                debug.error(\"lostVideo.js\", e);\n            }\n            if (!result[0] || !result[1]) {\n                try { // 标题或封面无效,尝试访问Biliplus CID缓存库\n                    let data = await xhr.GM({ url: `https://www.biliplus.com/all/video/av${aid}/` });\n                    if (data.match('/api/view_all?')) {\n                        data = data.match(/\\/api\\/view_all\\?.+?\\',cloudmoe/)[0].replace(/\\',cloudmoe/, \"\");\n                        data = await xhr.GM({ url: `//www.biliplus.com${data}` });\n                        data = API.jsonCheck(data).data;\n                        result[0] = result[0] || data.info.title;\n                        result[1] = result[1] || data.info.pic;\n                    }\n                }\n                catch (e) {\n                    debug.error(\"lostVideo.js\", e);\n                }\n            }\n            if (!result[0] || !result[1]) {\n                try { // 标题或封面依旧无效,尝试访问jijidown\n                    let data = await xhr.GM({ url: `https://www.jijidown.com/video/${aid}` });\n                    if (data.match('window._INIT')) {\n                        result[0] = result[0] || data.match(/\\<title\\>.+?\\-哔哩哔哩唧唧/)[0].replace(/<title>/, \"\").replace(/-哔哩哔哩唧唧/, \"\");\n                        result[1] = result[1] || data.match(/\\\"img\\\":\\ \\\".+?\\\",/)[0].match(/http.+?\\\",/)[0].replace(/\",/, \"\");\n                    }\n                }\n                catch (e) {\n                    debug.error(\"lostVideo.js\", e);\n                }\n            }\n            result[0] = result[0] || `av${aid}`; // 无法获取有效数据,将标题改为av号\n            result[1] = result[1] ? result[1].replace(\"http:\", \"\") : \"//i0.hdslb.com/bfs/archive/be27fd62c99036dce67efface486fb0a88ffed06.jpg\"; //无法获取有效数据,将封面改为哭脸\n            return result;\n        }\n        API.observerAddedNodes((node) => {\n            if (/section channel guest/.test(node.className)) {\n                let items = node.querySelectorAll(\".small-item.disabled\");\n                items.forEach(d => {\n                    let aid = d.getAttribute(\"data-aid\"); // 获取aid\n                    aid = Number(aid) || API.abv(aid); // 转化为数字\n                    d.setAttribute(\"class\", \"small-item fakeDanmu-item\");\n                    d.setAttribute(\"data-aid\", aid);\n                    d.children[0].href = `//www.bilibili.com/video/av${aid}`;\n                    d.children[1].href = `//www.bilibili.com/video/av${aid}`;\n                    d.children[0].setAttribute(\"target\", \"_blank\");\n                    d.children[1].setAttribute(\"target\", \"_blank\");\n                    d.children[0].setAttribute(\"class\", \"cover cover-normal\");\n                    d.children[1].setAttribute(\"style\", \"text-decoration : line-through;color : #ff0000;\");\n                    getLostVideo(aid).then(data => {\n                        d.children[1].setAttribute(\"title\", data[0]);\n                        d.children[1].text = data[0];\n                        d.children[0].children[0].alt = data[0];\n                        d.children[0].children[0].src = data[1];\n                    });\n                });\n            }\n            if (/small-item disabled/.test(node.className)) {\n                let aid = node.getAttribute(\"data-aid\"); // 获取aid\n                aid = Number(aid) || API.abv(aid); // 转化为数字\n                node.setAttribute(\"class\", \"small-item fakeDanmu-item\");\n                node.setAttribute(\"data-aid\", aid);\n                node.children[0].href = `//www.bilibili.com/video/av${aid}`;\n                node.children[1].href = `//www.bilibili.com/video/av${aid}`;\n                node.children[0].setAttribute(\"target\", \"_blank\");\n                node.children[1].setAttribute(\"target\", \"_blank\");\n                node.children[0].setAttribute(\"class\", \"cover cover-normal\");\n                node.children[1].setAttribute(\"style\", \"text-decoration : line-through;color : #ff0000;\");\n                getLostVideo(aid).then(data => {\n                    node.children[1].setAttribute(\"title\", data[0]);\n                    node.children[1].text = data[0];\n                    node.children[0].children[0].alt = data[0];\n                    node.children[0].children[0].src = data[1];\n                });\n            }\n        });\n    }\n    catch (e) {\n        toast.error(\"lostVideo.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/space/lostVideo.js";
    modules["midInfo.js"] = "/**\n * 本模块负责修复对于番剧出差(uid=11783021)空间的访问\n */\n(function () {\n    try {\n        /**\n         * 备份的uid信息,可能需要偶尔更新一下?\n         */\n        const response = API.getModule(\"mid.json\");\n        response.data.mid = API.mid;\n        switch (Number(API.mid)) {\n            case 11783021:\n                response.data.name = \"哔哩哔哩番剧出差\";\n                response.data.official.desc = \"哔哩哔哩番剧出差 官方帐号\";\n                break;\n            case 1988098633:\n                response.data.name = \"b站_DM組\";\n                response.data.official.desc = \"b站_DM組 官方帐号\";\n                break;\n            case 2042149112:\n                response.data.name = \"b站_EN組\";\n                response.data.official.desc = \"b站_EN組 官方帐号\";\n                break;\n        }\n        API.xhrhook([\"api.bilibili.com/x/space/acc/info\"], function (args) {\n            this.addEventListener('readystatechange', () => {\n                if (this.readyState === 4) {\n                    if (this.responseText && this.responseText.includes(\"-404\")) {\n                        Object.defineProperty(this, 'response', { writable: true });\n                        Object.defineProperty(this, 'responseText', { writable: true });\n                        this.response = this.responseText = JSON.stringify(response);\n                        toast.warning(\"该用户被404,已使用缓存数据恢复访问!\");\n                    }\n                }\n            });\n        });\n    }\n    catch (e) {\n        toast.error(\"11783021.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/space/midInfo.js";
    modules["space.js"] = "/**\n * 本模块负责引导个人空间相关的模块\n */\n(function () {\n    try {\n        API.mid = (API.path[3] && API.path[3].split(\"?\")[0]) || API.mid;\n        config.errands && (API.mid == 11783021 || API.mid == 1988098633 || API.mid == 2042149112) && API.importModule(\"midInfo.js\");\n        config.album && API.importModule(\"album.js\");\n        config.jointime && API.importModule(\"jointime.js\");\n        config.lostVideo && API.importModule(\"lostVideo.js\");\n    }\n    catch (e) {\n        toast.error(\"space.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/match/space/space.js";
    modules["accesskey.js"] = "/**\n * 本模块负责获取账户授权的高级操作\n * 用于提供给代理服务器以获取区域/APP限制视频源,实际上不进行授权也行,以游客身份一般一样能获取最高1080P的视频源,而限制视频一般也不要求大会员\n * **账户授权意味着第三方拥有您B站账号的访问权限,如非必要请不要进行操作!**\n */\n(function () {\n    class Accesskey {\n        constructor() {\n            this.access_key = GM.getValue(\"access_key\", \"\");\n            this.access_date = GM.getValue(\"access_date\", 0);\n            this.num = 0;\n            this.box = API.element.popupbox({ maxWidth: \"360px\", maxHeight: \"300px\" });\n            API.addElement(\"div\", { style: 'text-align: center;font-size: 16px;font-weight: bold;margin-bottom: 10px;' }, this.box, `<span>账户授权<span>`);\n            API.addElement(\"div\", { style: 'margin-bottom: 10px;' }, this.box, `<div>授权代理服务器使用您的账户权限,以在限制视频等操作中继承您的大会员权益。\n            <strong>这意味着第三方拥有您的账户访问权限,请充分考虑其中干系后谨慎操作!</strong>\n            如果只是为了解除视频限制,以“游客”身份也一样可以获取到最高1080P的视频源,而且一般不会有大会员专享限制。\n            </br>※ 鉴权有效期一般在一个月左右,若是失效需要手动重新授权,脚本不会代为检查。</div>`);\n            this.box.appendChild(API.element.hr());\n            const body = API.addElement(\"div\", { style: \"display: flex;align-items: center;justify-content: space-around;margin-bottom: 10px;\" }, this.box);\n            this.enable = body.appendChild(API.element.button(() => { this.access(); }, \"开始授权\", 3));\n            this.disable = body.appendChild(API.element.button(() => { this.abort(); }, \"取消授权\", 10));\n            this.box.appendChild(API.element.hr());\n            this.foot = API.addElement(\"div\", { style: \"display: flex;align-items: center;justify-content: space-around;\" }, this.box);\n            this.flesh();\n        }\n        flesh() {\n            if (this.access_key) {\n                const temp = API.element.button(() => { this.access(); }, \"重新授权\", 3);\n                this.enable.replaceWith(temp);\n                this.disable.style.display = \"block\";\n                this.enable = temp;\n                this.foot.innerHTML = `<div>授权状态:已授权</div><div>授权日期:${API.timeFormat(this.access_date, true)}</div>`;\n            }\n            else {\n                const temp = API.element.button(() => { this.access(); }, \"开始授权\", 3);\n                this.enable.replaceWith(temp);\n                this.enable = temp;\n                this.disable.style.display = \"none\";\n                this.foot.innerHTML = `<div>授权状态:未授权</div><div> </div>`;\n            }\n        }\n        async access() {\n            if (!API.uid)\n                return (toast.warning(\"请先登录!\"), API.biliQuickLogin());\n            toast(\"您正在进行账户授权操作,请稍候~\");\n            let data = await xhr.GM({\n                url: API.urlsign(\"https://passport.bilibili.com/login/app/third?api=https%3A%2F%2Fwww.mcbbs.net%2Ftemplate%2Fmcbbs%2Fimage%2Fspecial_photo_bg.png\", undefined, 3),\n                responseType: \"json\"\n            });\n            data = await new Promise((resolve, reject) => {\n                GM.xmlHttpRequest({\n                    method: \"GET\",\n                    url: data.data.confirm_uri,\n                    onload: (xhr) => resolve(xhr.finalUrl),\n                    onerror: (xhr) => reject(xhr),\n                });\n            });\n            data = API.urlObj(data);\n            await new Promise((resolve, reject) => { this.pluslogin(data, resolve, reject); });\n            this.access_key = data.access_key;\n            this.access_date = new Date().getTime();\n            GM.setValue(\"access_key\", this.access_key);\n            GM.setValue(\"access_date\", this.access_date);\n            toast.success(\"账户授权成功!\");\n            this.flesh();\n        }\n        async abort() {\n            toast(\"正在取消账户授权,请稍候~\");\n            this.access_key = \"\";\n            this.access_date = 0;\n            GM.deleteValue(\"access_key\");\n            GM.deleteValue(\"access_date\");\n            await new Promise((resolve) => {\n                const iframe = document.createElement(\"iframe\");\n                iframe.setAttribute(\"style\", \"width: 0px;height: 0px;\");\n                iframe.src = \"https://www.biliplus.com/login?act=logout\";\n                iframe.onload = () => {\n                    iframe.remove();\n                    resolve();\n                };\n                iframe.onerror = () => {\n                    iframe.remove();\n                    resolve();\n                };\n                document.body.appendChild(iframe);\n            });\n            toast.success(\"已取消账户授权并销毁痕迹!\");\n            this.flesh();\n        }\n        pluslogin(data, resolve, reject) {\n            this.num++;\n            const iframe = document.createElement(\"iframe\");\n            iframe.setAttribute(\"style\", \"width: 0px;height: 0px;\");\n            iframe.src = API.objUrl(\"https://www.biliplus.com/login\", data);\n            iframe.onload = () => {\n                iframe.remove();\n                resolve();\n            };\n            iframe.onerror = ev => {\n                if (this.num < 4) {\n                    toast.error(\"授权出错!将在3秒后重试~\", ev);\n                    setTimeout(() => this.pluslogin(data, resolve, reject), 3e3);\n                }\n                else {\n                    toast.error(\"重试终止!请参考控制台报错信息~\");\n                    reject(ev);\n                }\n            };\n            document.body.appendChild(iframe);\n        }\n    }\n    API.showAccesskey = () => {\n        try {\n            new Accesskey();\n        }\n        catch (e) {\n            toast.error(\"accesskey.js\", e);\n        }\n    };\n})();\n\n//# sourceURL=API://@bilibili/dist/required/accesskey.js";
    modules["allDanmaku.js"] = "/**\n * 本模块负责提供全弹幕装填工具\n */\n(function () {\n    class AllDanmaku {\n        constructor(callback) {\n            this.danmaku = [];\n            this.callback = callback;\n            toast(\"正在尝试获取全部弹幕请耐心等待。。。\", \"冷却延时请尽量调大,以免短时间内大量请求被临时封端口!\");\n            this.pubdate = new Date(2009, 0);\n            if (API.__INITIAL_STATE__) {\n                if (API.__INITIAL_STATE__.videoData && API.__INITIAL_STATE__.videoData.pubdate) {\n                    this.pubdate = new Date(1E3 * API.__INITIAL_STATE__.videoData.pubdate);\n                }\n                else if (API.__INITIAL_STATE__.epInfo && API.__INITIAL_STATE__.epInfo.pub_real_time) {\n                    this.pubdate = new Date(API.__INITIAL_STATE__.epInfo.pub_real_time);\n                }\n            }\n            else {\n                let time = document.querySelector(\"div.tm-info.tminfo > time\");\n                time && (this.pubdate = new Date(time.innerHTML));\n            }\n            this.pubdate = API.timeFormat(this.pubdate, true).split(\" \")[0]; // 视频上传日期\n            this.today = API.timeFormat(undefined, true).split(\" \")[0]; // 当天日期\n            this.time = this.today;\n            this.arrP = this.pubdate.split(\"-\");\n            this.danmaku = [];\n            this.init();\n        }\n        /**\n         * 按日期拉取弹幕\n         * @returns 调用月份判断\n         */\n        async init() {\n            if (!API.uid)\n                return toast.warning(\"本功能需要登录!\");\n            if (!this.pubdate)\n                return toast.warning(\"投稿日期获取失败!无法获取全部弹幕!\");\n            try {\n                // 获取当日日期\n                this.arrT = this.time.split(\"-\");\n                // 如果年份小于投稿日,说明获取成功\n                if (this.arrT[0] < this.arrP[0])\n                    return this.done(1);\n                // 年份相等但月份小于投稿日说明获取成功\n                if (this.arrT[0] == this.arrP[0] && this.arrT[1] < this.arrP[1])\n                    return this.done(1);\n                // 年月都相等,但日期小于投稿日说明获取成功\n                if (this.arrT[0] == this.arrP[0] && this.arrT[1] == this.arrP[1] && this.arrT[2] < this.arrP[2])\n                    return this.done(1);\n                // 日期未早于投稿日,正常请求日期数据\n                toast(\"正在获取 \" + this.time + \" 日的弹幕。。。\");\n                let danmaku = await API.getHistoryDanmaku(this.time);\n                API.sortDmById(danmaku, \"idStr\");\n                danmaku.reverse();\n                // 取最早一条弹幕的时间\n                this.time = API.timeFormat(danmaku[danmaku.length - 1].ctime * 1000, true).split(\" \")[0];\n                this.danmaku = this.danmaku.concat(danmaku);\n                toast(\"数据返回!已获取弹幕数:\" + API.unitFormat(this.danmaku.length));\n                this.arrT = this.time.split(\"-\");\n                // 如果当天不是投稿日,转入日期检查\n                if (this.pubdate != this.today)\n                    return this.check();\n                // 否则结束弹幕获取,当前弹幕就是能获取到的全弹幕\n                this.done(1);\n            }\n            catch (e) {\n                e = Array.isArray(e) ? e : [e];\n                toast.error(\"全弹幕装填\", ...e);\n                // 弹幕获取出错,载入已获取的弹幕\n                if (this.danmaku[0]) {\n                    toast.warning(\"弹幕获取出错!\", \"保留并载入已获取的弹幕\");\n                    this.done();\n                }\n                else {\n                    this.callback && this.callback();\n                    toast.error(\"弹幕获取出错!\", \"已退出!\");\n                }\n            }\n        }\n        /**\n         * 按月份判断有弹幕时间\n         * @returns 调用获取日期弹幕或者循环月份判断\n         */\n        async check() {\n            try {\n                // 如果年份小于投稿日,说明获取成功\n                if (this.arrT[0] < this.arrP[0])\n                    return this.done(1);\n                // 年份相等但月份小于投稿日说明获取成功\n                if (this.arrT[0] == this.arrP[0] && this.arrT[1] < this.arrP[1])\n                    return this.done(1);\n                // 年月都相等,但日期小于投稿日说明获取成功\n                if (this.arrT[0] == this.arrP[0] && this.arrT[1] == this.arrP[1] && this.arrT[2] < this.arrP[2])\n                    return this.done(1);\n                // 日期未早于投稿日,正常请求月份数据\n                let data = await xhr({\n                    url: API.objUrl(\"https://api.bilibili.com/x/v2/dm/history/index\", {\n                        type: 1,\n                        oid: API.cid,\n                        month: this.arrT.slice(0, 2).join(\"-\")\n                    }),\n                    credentials: true\n                });\n                data = API.jsonCheck(data).data;\n                if (data && data[0]) {\n                    // 当月有弹幕,进入日期判断\n                    for (let i = data.length - 1; i >= 0; i--) {\n                        let date = data[i].split(\"-\");\n                        if (date[2] < this.arrT[2]) {\n                            // 当日在已获取弹幕之前,记录并跳出循环\n                            this.timeT = data[i];\n                            break;\n                        }\n                    }\n                    if (this.timeT) {\n                        // 延时转入日期请求\n                        this.time = this.timeT;\n                        this.timeT = undefined;\n                        toast(`技能冷却中。。。请稍待 ${config.allDanmakuDelay} 秒钟`);\n                        return setTimeout(() => this.init(), config.allDanmakuDelay * 1000);\n                    }\n                    else {\n                        // 当月有弹幕但都不在已请求日之前,月份 -1 重载\n                        if (this.arrT[1] > 1) {\n                            this.arrT[1]--;\n                            this.arrT[1] = (Array(2).join('0') + this.arrT[1]).slice(-2);\n                        }\n                        else\n                            this.arrT = [this.arrT[0] - 1, 12, 31];\n                        toast(`获取前一个月数据 ${this.arrT.slice(0, 2).join(\"-\")} 请稍待 ${config.allDanmakuDelay} 秒钟`);\n                        return setTimeout(() => this.check(), config.allDanmakuDelay * 1000);\n                    }\n                }\n                else {\n                    // 当月无弹幕直接月份 -1 重载,月份等于 1 则取上年最后一天\n                    if (this.arrT[1] > 1) {\n                        this.arrT[1]--;\n                        if (this.arrT[1] < 10)\n                            this.arrT[1] = (Array(2).join('0') + this.arrT[1]).slice(-2);\n                    }\n                    else\n                        this.arrT = [this.arrT[0] - 1, 12, 31];\n                    toast(`获取前一个月数据 ${this.arrT.slice(0, 2).join(\"-\")} 请稍待 ${config.allDanmakuDelay} 秒钟`);\n                    return setTimeout(() => this.check(), config.allDanmakuDelay * 1000);\n                }\n            }\n            catch (e) {\n                e = Array.isArray(e) ? e : [e];\n                toast.error(\"全弹幕装填\", ...e);\n                // 弹幕获取出错,载入已获取的弹幕\n                if (this.danmaku[0]) {\n                    toast.warning(\"弹幕获取出错!\", \"保留并载入已获取的弹幕\");\n                    this.done();\n                }\n                else {\n                    this.callback && this.callback();\n                    toast.error(\"弹幕获取出错!\", \"已退出!\");\n                }\n            }\n        }\n        /**\n         * 载入弹幕\n         * @param boolean 判断获取成功还是失败,成功请传入真值。\n         */\n        async done(boolean) {\n            var _a;\n            try {\n                // 历史弹幕里不包含代码弹幕必须额外处理\n                toast(\"正在获取BAS/代码弹幕专包。。。\");\n                this.danmaku = this.danmaku.concat(await API.getSegDanmaku(undefined, undefined, true));\n                toast(\"数据返回!正在整合。。。\");\n            }\n            catch (e) { }\n            let danmaku = API.danmakuFormat(this.danmaku, API.aid);\n            if (boolean)\n                toast.success(\"全弹幕获取成功,正在装填。。。\", \"总弹幕量:\" + API.unitFormat(this.danmaku.length), \"同时推送至下载面板,可右键保存 π_π\");\n            (_a = window.player) === null || _a === void 0 ? void 0 : _a.setDanmaku(danmaku);\n            API.danmaku = danmaku;\n            this.callback && this.callback();\n        }\n    }\n    API.allDanmaku = (callback) => {\n        try {\n            new AllDanmaku(callback);\n        }\n        catch (e) {\n            toast.error(\"allDanmaku.js\", e);\n        }\n    };\n})();\n\n//# sourceURL=API://@bilibili/dist/required/allDanmaku.js";
    modules["autoFix.js"] = "/**\n * 本模块负责一些自动化处理\n */\n(function () {\n    try {\n        function bofqiToView() {\n            let str = [\".bangumi_player\", \"#bofqi\", \"#bilibiliPlayer\"];\n            let node = str.reduce((s, d) => {\n                s = s || document.querySelector(d);\n                return s;\n            }, document.querySelector(\"#__bofqi\"));\n            node && node.scrollIntoView({ behavior: 'smooth', block: 'center' });\n        }\n        API.switchVideo(() => {\n            config.danmakuFirst && document.querySelectorAll(\".bilibili-player-filter-btn\")[1].click();\n            setTimeout(() => {\n                config.showBofqi && bofqiToView();\n                config.screenWide && document.querySelector(\".bilibili-player-iconfont.bilibili-player-iconfont-widescreen.icon-24wideoff\") && document.querySelector(\".bilibili-player-video-btn.bilibili-player-video-btn-widescreen\").click();\n                if (config.noDanmaku && !document.querySelector(\".bilibili-player-video-btn.bilibili-player-video-btn-danmaku.video-state-danmaku-off\")) {\n                    if (document.querySelector(\".bilibili-player-video-btn.bilibili-player-video-btn-danmaku\")) {\n                        document.querySelector(\".bilibili-player-video-btn.bilibili-player-video-btn-danmaku\").click(); // 自动关闭弹幕\n                    }\n                }\n            }, 500);\n            config.autoPlay && setTimeout(() => { window.player && window.player.play && window.player.play(); }, 1000);\n        });\n        API.path.name && API.observerAddedNodes(e => {\n            if (e.className && /bilibili-player-danmaku-setting-lite-panel/.test(e.className)) {\n                API.runWhile(() => document.querySelector(\".bilibili-player-setting-dmask-wrap\"), () => {\n                    const node = document.querySelector(\".bilibili-player-setting-dmask-wrap\").parentElement;\n                    const lebel = API.addElement(\"label\", { class: \"bpui-checkbox-text\", style: \"cursor: pointer;display: inline-table;\" }, node, \"本地文件\");\n                    const input = API.addElement(\"input\", { type: \"file\", accept: \".mp4,.xml,.json\", multiple: \"multiple\", style: \"width: 0;\" }, lebel);\n                    input.onchange = () => {\n                        var _a;\n                        (!((_a = window.player) === null || _a === void 0 ? void 0 : _a.setDanmaku)) && toast.warning(\"内部组件丢失,无法载入弹幕文件!\");\n                        API.localMedia(input.files);\n                    };\n                });\n            }\n        });\n    }\n    catch (e) {\n        debug.error(\"autoFix.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/required/autoFix.js";
    modules["banner.js"] = "/**\n * 本模块负责替换顶栏动图接口\n * 本模块动态banner相关代码移植自B站header.js\n */\n(function () {\n    var _a;\n    try {\n        class Animate {\n            constructor(v) {\n                /**\n                 * 有在启用了动画banner的配置,且浏览器支持css filter时才加载动画banner的图片资源\n                 * safari浏览器在mac屏幕上模糊效果有性能问题,不开启\n                 */\n                this.animatedBannerSupport = typeof CSS !== 'undefined' && CSS.supports && CSS.supports('filter: blur(1px)')\n                    && !/^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n                this.resources = [];\n                /**\n                 * container 元素上有其他元素,需使用全局事件判断鼠标位置\n                 */\n                this.entered = false;\n                this.extensions = [];\n                if (this.animatedBannerSupport)\n                    this.mounted(v);\n                API.addCss(API.getModule(\"animated-banner.css\"), \"animated-banner\");\n                if (v.is_split_layer !== 0) {\n                    API.addCss(\".blur-bg {display:none}\");\n                }\n                else\n                    API.addCss(\".blur-bg {background:none !important;-webkit-backdrop-filter: blur(4px);backdrop-filter: blur(4px)}\");\n            }\n            static resourceId() {\n                if (location.href.includes(\"v/douga\"))\n                    return 1576;\n                if (location.href.includes(\"/anime\"))\n                    return 1612;\n                if (location.href.includes(\"v/music\"))\n                    return 1580;\n                if (location.href.includes(\"/guochuang\"))\n                    return 1920;\n                if (location.href.includes(\"v/dance\"))\n                    return 1584;\n                if (location.href.includes(\"v/game\"))\n                    return 1588;\n                if (location.href.includes(\"v/knowledge\"))\n                    return 1592;\n                if (location.href.includes(\"v/tech\"))\n                    return 3129;\n                if (location.href.includes(\"v/life\"))\n                    return 1600;\n                if (location.href.includes(\"v/kichiku\"))\n                    return 1608;\n                if (location.href.includes(\"v/fashion\"))\n                    return 1604;\n                if (location.href.includes(\"v/ent\"))\n                    return 1596;\n                if (location.href.includes(\"v/cinephile\"))\n                    return 2210;\n                if (location.href.includes(\"/cinema\"))\n                    return 1634;\n                return 142;\n            }\n            async mounted(v) {\n                this.layerConfig = JSON.parse(v.split_layer);\n                if (!this.layerConfig.layers)\n                    return;\n                try {\n                    if (\"extensions\" in this.layerConfig && \"time\" in this.layerConfig.extensions) {\n                        let time, now = (Date.now() - (new Date).setHours(0, 0, 0, 0)) / 1e3;\n                        let timeCode = Object.keys(this.layerConfig.extensions.time).sort((a, b) => parseInt(a) - parseInt(b));\n                        for (let t of timeCode) {\n                            if (parseInt(t) < now)\n                                time = parseInt(t);\n                            else\n                                break;\n                        }\n                        let timelayers = this.layerConfig.extensions.time[time];\n                        this.layerConfig.layers = timelayers[Math.floor(Math.random() * timelayers.length)].layers;\n                    }\n                    await Promise.all(this.layerConfig.layers.map(async (v, index) => {\n                        return Promise.all(v.resources.map(async (i) => {\n                            if (/\\.(webm|mp4)$/.test(i.src)) {\n                                const res = await xhr({ url: i.src, responseType: \"blob\" });\n                                const url = URL.createObjectURL(res);\n                                const video = document.createElement('video');\n                                video.muted = true;\n                                // video.autoplay = true\n                                video.loop = true;\n                                video.src = url;\n                                video.playsInline = true;\n                                video.style.objectFit = 'cover'; // 元素尺寸大于视频实际尺寸时放大\n                                this.resources[index] = video;\n                                // 视频需要添加到dom树才能获取宽高\n                                video.width = 0;\n                                video.height = 0;\n                                document.body.appendChild(video);\n                                await new Promise(resolve => {\n                                    const onMetaLoad = () => {\n                                        resolve(true);\n                                        video.removeEventListener('loadedmetadata', onMetaLoad);\n                                    };\n                                    video.addEventListener('loadedmetadata', onMetaLoad);\n                                });\n                            }\n                            else {\n                                const img = document.createElement('img');\n                                img.src = i.src;\n                                await new Promise(resolve => img.onload = resolve);\n                                this.resources[index] = img;\n                            }\n                        }));\n                    }));\n                }\n                catch (e) {\n                    debug.error('load animated banner images error', e);\n                    return;\n                }\n                let container = document.querySelector(\"#banner_link\");\n                if (!container) {\n                    container = document.querySelector(\".h-center\");\n                    if (!container)\n                        return;\n                    container.parentElement.removeAttribute(\"style\");\n                    container.style.width = \"100%\";\n                    container.style.top = \"-42px\";\n                    container.style.marginBottom = \"-42px\";\n                    container.innerHTML = \"\";\n                    document.querySelector(\".b-header-mask-wrp\").remove();\n                }\n                ;\n                container.classList.add(\"animated-banner\");\n                let containerHeight = container.clientHeight;\n                let containerWidth = container.clientWidth;\n                let containerScale = containerHeight / 155;\n                // 初始化资源尺寸\n                this.layerConfig.layers.forEach(v => {\n                    var _b, _c, _d, _e;\n                    v._initState = {\n                        scale: 1,\n                        rotate: ((_b = v.rotate) === null || _b === void 0 ? void 0 : _b.initial) || 0,\n                        translate: ((_c = v.translate) === null || _c === void 0 ? void 0 : _c.initial) || [0, 0],\n                        blur: ((_d = v.blur) === null || _d === void 0 ? void 0 : _d.initial) || 0,\n                        opacity: ((_e = v.opacity) === null || _e === void 0 ? void 0 : _e.initial) === undefined ? 1 : v.opacity.initial,\n                    };\n                    v.resources.forEach((i, index) => {\n                        var _b, _c;\n                        const el = this.resources[index];\n                        if (el.tagName === 'VIDEO') {\n                            if (el.parentNode) {\n                                el.parentNode.removeChild(el);\n                            }\n                            el.dataset.height = el.videoHeight;\n                            el.dataset.width = el.videoWidth;\n                        }\n                        else {\n                            el.dataset.height = el.naturalHeight;\n                            el.dataset.width = el.naturalWidth;\n                        }\n                        const initial = ((_b = v.scale) === null || _b === void 0 ? void 0 : _b.initial) === undefined ? 1 : (_c = v.scale) === null || _c === void 0 ? void 0 : _c.initial;\n                        el.height = el.dataset.height * containerScale * initial;\n                        el.width = el.dataset.width * containerScale * initial;\n                    });\n                });\n                // 初始化图层\n                const layers = this.layerConfig.layers.map(v => {\n                    const layer = document.createElement('div');\n                    layer.classList.add('layer');\n                    container.appendChild(layer);\n                    return layer;\n                });\n                let displace = 0;\n                let enterX = 0;\n                let raf = 0;\n                const curveParameterToFunc = (param) => {\n                    const o = API.bezier(...param);\n                    return v => v > 0 ? o(v) : -o(-v);\n                };\n                let lastDisplace = NaN;\n                // 根据鼠标位置改变状态\n                const af = t => {\n                    try {\n                        if (lastDisplace === displace) {\n                            return;\n                        }\n                        lastDisplace = displace;\n                        layers.map((layer, i) => {\n                            const v = this.layerConfig.layers[i];\n                            const a = layer.firstChild;\n                            if (!a) {\n                                return;\n                            }\n                            const transform = {\n                                scale: v._initState.scale,\n                                rotate: v._initState.rotate,\n                                translate: v._initState.translate,\n                            };\n                            if (v.scale) {\n                                const x = v.scale.offset || 0;\n                                const itp = v.scale.offsetCurve ? curveParameterToFunc(v.scale.offsetCurve) : (x => x);\n                                const offset = x * itp(displace);\n                                transform.scale = v._initState.scale + offset;\n                            }\n                            if (v.rotate) {\n                                const x = v.rotate.offset || 0;\n                                const itp = v.rotate.offsetCurve ? curveParameterToFunc(v.rotate.offsetCurve) : (x => x);\n                                const offset = x * itp(displace);\n                                transform.rotate = v._initState.rotate + offset;\n                            }\n                            if (v.translate) {\n                                const x = v.translate.offset || [0, 0];\n                                const itp = v.translate.offsetCurve ? curveParameterToFunc(v.translate.offsetCurve) : (x => x);\n                                const offset = x.map(v => itp(displace) * v);\n                                const translate = v._initState.translate.map((x, i) => { var _b; return (x + offset[i]) * containerScale * (((_b = v.scale) === null || _b === void 0 ? void 0 : _b.initial) || 1); });\n                                transform.translate = translate;\n                            }\n                            a.style.transform = `scale(${transform.scale})` +\n                                `translate(${transform.translate[0]}px, ${transform.translate[1]}px)` +\n                                `rotate(${transform.rotate}deg)`;\n                            if (v.blur) {\n                                const x = v.blur.offset || 0;\n                                const itp = v.blur.offsetCurve ? curveParameterToFunc(v.blur.offsetCurve) : (x => x);\n                                const blurOffset = x * itp(displace);\n                                let res = 0;\n                                if (!v.blur.wrap || v.blur.wrap === 'clamp') {\n                                    res = Math.max(0, v._initState.blur + blurOffset);\n                                }\n                                else if (v.blur.wrap === 'alternate') {\n                                    res = Math.abs(v._initState.blur + blurOffset);\n                                }\n                                a.style.filter = res < 1e-4 ? '' : `blur(${res}px)`;\n                            }\n                            if (v.opacity) {\n                                const x = v.opacity.offset || 0;\n                                const itp = v.opacity.offsetCurve ? curveParameterToFunc(v.opacity.offsetCurve) : (x => x);\n                                const opacityOffset = x * itp(displace);\n                                const initial = v._initState.opacity;\n                                if (!v.opacity.wrap || v.opacity.wrap === 'clamp') {\n                                    a.style.opacity = Math.max(0, Math.min(1, initial + opacityOffset));\n                                }\n                                else if (v.opacity.wrap === 'alternate') {\n                                    const x = initial + opacityOffset;\n                                    let y = Math.abs(x % 1);\n                                    if (Math.abs(x % 2) >= 1) {\n                                        y = 1 - y;\n                                    }\n                                    a.style.opacity = y;\n                                }\n                            }\n                        });\n                    }\n                    catch (e) {\n                        debug.error(e);\n                    }\n                };\n                // 初始化图层内图片和帧动画\n                this.layerConfig.layers.map((v, i) => {\n                    const a = this.resources[i];\n                    layers[i].appendChild(a);\n                    if (a.tagName === 'VIDEO') {\n                        a.play();\n                    }\n                    requestAnimationFrame(af);\n                });\n                const handleLeave = () => {\n                    const now = performance.now();\n                    const timeout = 200;\n                    const tempDisplace = displace;\n                    cancelAnimationFrame(raf);\n                    const leaveAF = t => {\n                        if (t - now < timeout) {\n                            displace = tempDisplace * (1 - (t - now) / 200);\n                            af(t);\n                            requestAnimationFrame(leaveAF);\n                        }\n                        else {\n                            displace = 0;\n                            af(t);\n                        }\n                    };\n                    raf = requestAnimationFrame(leaveAF);\n                };\n                this.handleMouseLeave = e => {\n                    this.entered = false;\n                    handleLeave();\n                };\n                this.handleMouseMove = e => {\n                    const offsetY = document.documentElement.scrollTop + e.clientY;\n                    if (offsetY < containerHeight) {\n                        if (!this.entered) {\n                            this.entered = true;\n                            enterX = e.clientX;\n                        }\n                        displace = (e.clientX - enterX) / containerWidth;\n                        cancelAnimationFrame(raf);\n                        raf = requestAnimationFrame(af);\n                    }\n                    else {\n                        if (this.entered) {\n                            this.entered = false;\n                            handleLeave();\n                        }\n                    }\n                    this.extensions.map(v => { var _b; return (_b = v.handleMouseMove) === null || _b === void 0 ? void 0 : _b.call(v, { e, displace }); });\n                };\n                this.handleResize = e => {\n                    containerHeight = container.clientHeight;\n                    containerWidth = container.clientWidth;\n                    containerScale = containerHeight / 155;\n                    this.layerConfig.layers.forEach(lc => {\n                        lc.resources.forEach((d, i) => {\n                            var _b, _c;\n                            const el = this.resources[i];\n                            el.height = el.dataset.height * containerScale * (((_b = lc.scale) === null || _b === void 0 ? void 0 : _b.initial) || 1);\n                            el.width = el.dataset.width * containerScale * (((_c = lc.scale) === null || _c === void 0 ? void 0 : _c.initial) || 1);\n                        });\n                    });\n                    cancelAnimationFrame(raf);\n                    raf = requestAnimationFrame(t => {\n                        af(t);\n                    });\n                    this.extensions.map(v => { var _b; return (_b = v.handleResize) === null || _b === void 0 ? void 0 : _b.call(v, e); });\n                };\n                document.addEventListener('mouseleave', this.handleMouseLeave);\n                window.addEventListener('mousemove', this.handleMouseMove);\n                window.addEventListener('resize', this.handleResize);\n            }\n        }\n        _a = Animate;\n        Animate.rid = _a.resourceId();\n        Animate.locs = [1576, 1612, 1580, 1920, 1584, 1588, 1592, 3129, 1600, 1608, 1604, 1596, 2210, 1634, 142];\n        config.bannerGif && API.jsonphook([\"api.bilibili.com/x/web-interface/index/icon\"], function (xhr) {\n            const obj = API.urlObj(xhr.url);\n            let callback = obj.callback;\n            let call = window[callback];\n            if (call) {\n                window[callback] = function (v) {\n                    v.data = API.randomArray(JSON.parse(GM.getResourceText(\"index-icon.json\")).fix, 1)[0];\n                    return call(v);\n                };\n            }\n        });\n        let tag = false; // 防止二度请求\n        API.jsonphook([\"api.bilibili.com/x/web-show/res/loc\"], function (jsonp) {\n            const obj = API.urlObj(jsonp.url);\n            let callback = obj.callback;\n            let call = window[callback];\n            if (call) {\n                window[callback] = function (v) {\n                    const data = GM.getValue(\"banner\");\n                    v.data && Animate.locs.forEach(d => {\n                        v.data[d] && (v.data[d][0].pic = (data && data.pic) || \"//i0.hdslb.com/bfs/activity-plat/static/20171220/68a052f664e8414bb594f9b00b176599/images/90w1lpp6ry.png\",\n                            v.data[d][0].litpic = (data && data.litpic),\n                            v.data[d][0].url = (data && data.url) || \"\",\n                            v.data[d][0].title = (data && data.name) || \"\");\n                        if (jsonp.url.includes(\"loc?\") && obj.id == String(d)) {\n                            v.data[0].pic = (data && data.pic) || \"//i0.hdslb.com/bfs/activity-plat/static/20171220/68a052f664e8414bb594f9b00b176599/images/90w1lpp6ry.png\";\n                            v.data[0].litpic = (data && data.litpic) || \"\";\n                            v.data[0].url = (data && data.url) || \"\";\n                            v.data[0].title = (data && data.name) || \"\";\n                        }\n                    });\n                    return call(v);\n                };\n            }\n            if (tag)\n                return;\n            tag = true;\n            xhr({\n                url: `https://api.bilibili.com/x/web-show/page/header?resource_id=${Animate.rid}`,\n                responseType: \"json\",\n                credentials: true\n            }).then((d) => {\n                GM.setValue(\"banner\", d.data);\n                new Animate(d.data);\n            });\n        });\n    }\n    catch (e) {\n        toast.error(\"banner.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/required/banner.js";
    modules["closedCaption.js"] = "/**\n * 本模块负责处理CC字幕\n * 代码移植自 Bilibili CC 字幕工具,源项目信息如下\n * @see indefined {@link https://github.com/indefined/UserScripts/tree/master/bilibiliCCHelper}\n */\n(function () {\n    class ClosedCaption {\n        constructor() {\n            this.element = {}; // 节点集合\n            this.data = {}; // 字幕缓存\n            this.resizeRate = 100; // 字幕大小倍率\n            this.ON = `<svg width=\"22\" height=\"28\" viewbox=\"0 0 22 30\" xmlns=\"http://www.w3.org/2000/svg\"><path id=\"svg_1\" fill-rule=\"evenodd\" fill=\"#99a2aa\" d=\"m4.07787,6.88102l14,0a2,2 0 0 1 2,2l0,10a2,2 0 0 1 -2,2l-14,0a2,2 0 0 1 -2,-2l0,-10a2,2 0 0 1 2,-2zm5,5.5a1,1 0 1 0 0,-2l-3,0a2,2 0 0 0 -2,2l0,3a2,2 0 0 0 2,2l3,0a1,1 0 0 0 0,-2l-2,0a1,1 0 0 1 -1,-1l0,-1a1,1 0 0 1 1,-1l2,0zm8,0a1,1 0 0 0 0,-2l-3,0a2,2 0 0 0 -2,2l0,3a2,2 0 0 0 2,2l3,0a1,1 0 0 0 0,-2l-2,0a1,1 0 0 1 -1,-1l0,-1a1,1 0 0 1 1,-1l2,0z\"/></svg>`;\n            this.OFF = `<svg width=\"22\" height=\"28\" viewBox=\"0 0 22 32\" xmlns=\"http://www.w3.org/2000/svg\"><path id=\"svg_1\" fill-rule=\"evenodd\" fill=\"#99a2aa\" d=\"m15.172,21.87103l-11.172,0a2,2 0 0 1 -2,-2l0,-10c0,-0.34 0.084,-0.658 0.233,-0.938l-0.425,-0.426a1,1 0 1 1 1.414,-1.414l15.556,15.556a1,1 0 0 1 -1.414,1.414l-2.192,-2.192zm-10.21,-10.21c-0.577,0.351 -0.962,0.986 -0.962,1.71l0,3a2,2 0 0 0 2,2l3,0a1,1 0 0 0 0,-2l-2,0a1,1 0 0 1 -1,-1l0,-1a1,1 0 0 1 0.713,-0.958l-1.751,-1.752zm1.866,-3.79l11.172,0a2,2 0 0 1 2,2l0,10c0,0.34 -0.084,0.658 -0.233,0.938l-2.48,-2.48a1,1 0 0 0 -0.287,-1.958l-1.672,0l-1.328,-1.328l0,-0.672a1,1 0 0 1 1,-1l2,0a1,1 0 0 0 0,-2l-3,0a2,2 0 0 0 -1.977,1.695l-5.195,-5.195z\"/></svg>`;\n            this.color = [\n                { value: '16777215', content: '<span style=\"color:#FFF;text-shadow: #000 0px 0px 1px\">白色</span>' },\n                { value: '16007990', content: '<b style=\"color:#F44336;text-shadow: #000 0px 0px 1px\">红色</b>' },\n                { value: '10233776', content: '<b style=\"color:#9C27B0;text-shadow: #000 0px 0px 1px\">紫色</b>' },\n                { value: '6765239', content: '<b style=\"color:#673AB7;text-shadow: #000 0px 0px 1px\">深紫色</b>' },\n                { value: '4149685', content: '<b style=\"color:#3F51B5;text-shadow: #000 0px 0px 1px\">靛青色</b>' },\n                { value: '2201331', content: '<b style=\"color:#2196F3;text-shadow: #000 0px 0px 1px\">蓝色</b>' },\n                { value: '240116', content: '<b style=\"color:#03A9F4;text-shadow: #000 0px 0px 1px\">亮蓝色</b>' }\n            ];\n            this.position = [\n                { value: 'bl', content: '左下角' },\n                { value: 'bc', content: '底部居中' },\n                { value: 'br', content: '右下角' },\n                { value: 'tl', content: '左上角' },\n                { value: 'tc', content: '顶部居中' },\n                { value: 'tr', content: '右上角' }\n            ];\n            this.shadow = [\n                { value: '0', content: '无描边', style: '' },\n                { value: '1', content: '重墨', style: `text-shadow: #000 1px 0px 1px, #000 0px 1px 1px, #000 0px -1px 1px,#000 -1px 0px 1px;` },\n                { value: '2', content: '描边', style: `text-shadow: #000 0px 0px 1px, #000 0px 0px 1px, #000 0px 0px 1px;` },\n                { value: '3', content: '45°投影', style: `text-shadow: #000 1px 1px 2px, #000 0px 0px 1px;` }\n            ];\n            this.isON = false; // 是否启用\n            this.setting = GM.getValue(\"subtitle\", { backgroundopacity: 0.5, color: 16777215, fontsize: 1, isclosed: false, scale: true, shadow: \"0\", position: 'bc' });\n            this.subtitlePrefer = GM.getValue(\"subtitlePrefer\"); // 默认语言\n        }\n        /**\n         * 绘制字幕面板\n         */\n        initUI() {\n            this.element.node = document.createElement(\"div\");\n            this.element.node.setAttribute(\"class\", \"bilibili-player-video-btn\");\n            this.element.node.setAttribute(\"id\", \"bilibili-player-subtitle-btn\");\n            this.element.node.setAttribute(\"style\", \"display: block;\");\n            this.element.span = API.addElement(\"span\", {}, this.element.node);\n            this.element.span.innerHTML = this.ON;\n            this.isON = true;\n            this.element.span.onclick = () => {\n                if (this.isON)\n                    this.iconSwitch();\n                else\n                    this.iconSwitch(this.caption);\n            };\n            this.element.table = API.addElement(\"div\", { id: \"subtitle-setting-panel\", style: \"position: absolute; bottom: 28px; right: 30px; background: white; border-radius: 4px; text-align: left; padding: 13px; display: none; cursor: default;\" }, this.element.node);\n            this.language();\n            this.fontsize();\n            this.fontcolor();\n            this.fontshadow();\n            this.fontposition();\n            this.fontopacrity();\n            API.addCss(API.getModule(\"closedCaption.css\"), \"caption\");\n            this.changeResize();\n            this.changePosition();\n        }\n        /**\n         * 切换字幕样式\n         */\n        changeStyle() {\n            var _a;\n            (_a = document.querySelector(\"#caption-style\")) === null || _a === void 0 ? void 0 : _a.remove();\n            API.addCss(`span.subtitle-item-background{opacity: ${this.setting.backgroundopacity};}\n            span.subtitle-item-text {color:#${(\"000000\" + this.setting.color.toString(16)).slice(-6)};}\n            span.subtitle-item {font-size: ${this.setting.fontsize * this.resizeRate}%;line-height: 110%;}\n            span.subtitle-item {${this.shadow[this.setting.shadow].style}}`, \"caption-style\");\n            GM.setValue(\"subtitle\", this.setting);\n        }\n        /**\n         * 切换字幕大小\n         */\n        changeResize() {\n            this.resizeRate = this.setting.scale ? window.player.getWidth() / 1280 * 100 : 100;\n            this.changeStyle();\n        }\n        /**\n         * 切换字幕位置\n         */\n        changePosition() {\n            this.contain = document.querySelector(\".bilibili-player-video-subtitle>div\");\n            this.contain.className = 'subtitle-position subtitle-position-'\n                + (this.setting.position || 'bc');\n            this.contain.style = '';\n            GM.setValue(\"subtitle\", this.setting);\n        }\n        /**\n         * 字幕图标切换\n         * @param caption\n         */\n        iconSwitch(caption) {\n            if (caption) {\n                this.isON = true;\n                this.element.span.innerHTML = this.ON;\n                this.setCaption(caption);\n                this.text.innerHTML = caption.lan_doc;\n                this.element.language.children[2].disabled = false;\n            }\n            else {\n                this.isON = false;\n                this.element.span.innerHTML = this.OFF;\n                this.setCaption();\n                this.text.innerHTML = \"关闭\";\n                this.element.language.children[2].disabled = true;\n            }\n        }\n        /**\n         * 字幕选择\n         */\n        language() {\n            this.element.language = API.addElement(\"div\", {}, this.element.table);\n            this.element.language.innerHTML = `<div>字幕</div>\n            <div class=\"bilibili-player-block-string-type bpui-component bpui-selectmenu selectmenu-mode-absolute\" style=\"width: 100px;\">\n            <div class=\"bpui-selectmenu-txt\">关闭</div>\n            <div class=\"bpui-selectmenu-arrow bpui-icon bpui-icon-arrow-down\"></div>\n            <ul class=\"bpui-selectmenu-list bpui-selectmenu-list-left\" style=\"max-height: 180px; overflow: hidden auto; white-space: nowrap;\">\n            <li class=\"bpui-selectmenu-list-row\" data-value=\"close\">关闭</li>\n            </ul></div>\n            <button class=\"bpui-button\" style=\"padding: 0px 8px;\">下载</button>\n            <a class=\"bpui-button\" href=\"https://member.bilibili.com/v2#/zimu/my-zimu/zimu-editor?cid=${API.cid}&aid=${API.aid}\" target=\"_blank\" title=\"\" style=\"margin-right: 0px; height: 24px; padding: 0px 6px;\">添加字幕</a>`;\n            let list = this.element.language.children[1].children[2];\n            this.text = this.element.language.children[1].children[0];\n            // this.element.language.children[2].onclick = () => {\n            //     API.importModule(\"download\");\n            //     API.config.reset.dlother = 1; // 开启其他下载\n            //     API.download(); // 拉起下载面板\n            // }\n            list.children[0].onclick = () => {\n                this.text.innerHTML = \"关闭\";\n                this.setCaption();\n            };\n            this.text.innerHTML = this.caption.lan_doc;\n            this.captions = this.captions.reverse();\n            this.captions.forEach((d) => {\n                let temp = API.addElement(\"div\", { class: \"bpui-selectmenu-list-row\", \"data-value\": d.lan }, list, d.lan_doc, true);\n                temp.onclick = () => {\n                    this.text.innerHTML = d.lan_doc;\n                    this.iconSwitch(d);\n                    GM.setValue(\"subtitlePrefer\", this.subtitlePrefer = d.lan);\n                };\n            });\n        }\n        /**\n         * 字幕大小\n         */\n        fontsize() {\n            this.element.fontsize = API.addElement(\"div\", {}, this.element.table);\n            this.element.fontsize.innerHTML = `<div>字体大小</div>\n            <input type=\"range\" step=\"25\" style=\"width: 70%;\">\n            <input id=\"subtitle-auto-resize\" type=\"checkbox\">\n            <label for=\"subtitle-auto-resize\" style=\"cursor: pointer;\">自动缩放</label>`;\n            this.element.fontsize.children[1].value = this.setting.fontsize == 0.6 ? 0\n                : this.setting.fontsize == 0.8 ? 25\n                    : this.setting.fontsize == 1.3 ? 75\n                        : this.setting.fontsize == 1.6 ? 100 : 50;\n            this.element.fontsize.children[1].oninput = (e) => {\n                const v = e.target.value / 25;\n                this.setting.fontsize = v > 2 ? (v - 2) * 0.3 + 1 : v * 0.2 + 0.6;\n                this.changeStyle();\n            };\n            this.element.fontsize.children[2].checked = this.setting.scale;\n            this.element.fontsize.children[2].onchange = (e) => this.changeResize(this.setting.scale = e.target.checked);\n        }\n        /**\n         * 字幕颜色\n         */\n        fontcolor() {\n            this.element.fontcolor = API.addElement(\"div\", {}, this.element.table);\n            this.element.fontcolor.innerHTML = `<span>字幕颜色</span>\n            <div class=\"bilibili-player-block-string-type bpui-component bpui-selectmenu selectmenu-mode-absolute\" style=\"width: 74%;\">\n            <div class=\"bpui-selectmenu-txt\"><span style=\"color:#FFF;text-shadow: #000 0px 0px 1px\">白色</span></div>\n            <div class=\"bpui-selectmenu-arrow bpui-icon bpui-icon-arrow-down\"></div>\n            <ul class=\"bpui-selectmenu-list bpui-selectmenu-list-left\" style=\"max-height: 120px; overflow: hidden auto; white-space: nowrap;\"></ul>\n            </div>`;\n            this.color.forEach(d => {\n                if (d.value == this.setting.color)\n                    this.element.fontcolor.children[1].children[0].innerHTML = d.content;\n                let temp = API.addElement(\"li\", { class: \"bpui-selectmenu-list-row\", \"data-value\": d.value }, this.element.fontcolor.children[1].children[2]);\n                temp.innerHTML = d.content;\n                temp.onclick = () => {\n                    this.element.fontcolor.children[1].children[0].innerHTML = d.content;\n                    this.changeStyle(this.setting.color = parseInt(d.value));\n                };\n            });\n        }\n        /**\n         * 字幕阴影\n         */\n        fontshadow() {\n            this.element.fontshadow = API.addElement(\"div\", {}, this.element.table);\n            this.element.fontshadow.innerHTML = `<span>字幕描边</span>\n            <div class=\"bilibili-player-block-string-type bpui-component bpui-selectmenu selectmenu-mode-absolute\" style=\"width: 74%;\">\n            <div class=\"bpui-selectmenu-txt\">无描边</div>\n            <div class=\"bpui-selectmenu-arrow bpui-icon bpui-icon-arrow-down\"></div>\n            <ul class=\"bpui-selectmenu-list bpui-selectmenu-list-left\" style=\"max-height: 120px; overflow: hidden auto; white-space: nowrap;\"></ul>\n            </div>`;\n            this.shadow.forEach(d => {\n                if (d.value == this.setting.shadow)\n                    this.element.fontshadow.children[1].children[0].innerHTML = d.content;\n                let temp = API.addElement(\"li\", { class: \"bpui-selectmenu-list-row\", \"data-value\": d.value }, this.element.fontshadow.children[1].children[2]);\n                temp.innerHTML = d.content;\n                temp.onclick = () => {\n                    this.element.fontshadow.children[1].children[0].innerHTML = d.content;\n                    this.changeStyle(this.setting.shadow = d.value);\n                };\n            });\n        }\n        /**\n         * 字幕位置\n         */\n        fontposition() {\n            this.element.fontposition = API.addElement(\"div\", {}, this.element.table);\n            this.element.fontposition.innerHTML = `<span>字幕位置</span>\n            <div class=\"bilibili-player-block-string-type bpui-component bpui-selectmenu selectmenu-mode-absolute\" style=\"width: 74%;\">\n            <div class=\"bpui-selectmenu-txt\">底部居中</div>\n            <div class=\"bpui-selectmenu-arrow bpui-icon bpui-icon-arrow-down\"></div>\n            <ul class=\"bpui-selectmenu-list bpui-selectmenu-list-left\" style=\"max-height: 100px; overflow: hidden auto; white-space: nowrap;\"></ul>\n            </div>`;\n            this.position.forEach(d => {\n                if (d.value == this.setting.position)\n                    this.element.fontposition.children[1].children[0].innerHTML = d.content;\n                let temp = API.addElement(\"li\", { class: \"bpui-selectmenu-list-row\", \"data-value\": d.value }, this.element.fontposition.children[1].children[2]);\n                temp.innerHTML = d.content;\n                temp.onclick = () => {\n                    this.element.fontposition.children[1].children[0].innerHTML = d.content;\n                    this.changePosition(this.setting.position = d.value);\n                };\n            });\n        }\n        /**\n         * 字幕透明度\n         */\n        fontopacrity() {\n            this.element.fontopacrity = API.addElement(\"div\", {}, this.element.table);\n            this.element.fontopacrity.innerHTML = `<div>背景不透明度</div><input type=\"range\" style=\"width: 100%;\">`;\n            this.element.fontopacrity.children[1].value = this.setting.backgroundopacity * 100;\n            this.element.fontopacrity.children[1].oninput = (e) => {\n                this.changeStyle(this.setting.backgroundopacity = e.target.value / 100);\n            };\n        }\n        /**\n         * 获取CC字幕信息\n         */\n        async getCaption(data) {\n            try {\n                API.subtitle = this.captions = data.data.subtitle.subtitles || [];\n                let i = 0; // 指示字幕语言记录\n                this.captions.forEach((d, j) => {\n                    if (d.lan == this.subtitlePrefer)\n                        i = j;\n                });\n                if (this.captions[i])\n                    await this.setCaption(this.captions[i]);\n                if (this.caption) {\n                    // 只在有字幕时添加面板\n                    window.player.addEventListener('video_resize', (event) => {\n                        this.changeResize(event);\n                    });\n                    let anchor = document.querySelector(\".bilibili-player-video-btn-quality\");\n                    this.initUI();\n                    if (!document.querySelector(\"#bilibili-player-subtitle-btn\"))\n                        anchor.insertAdjacentElement(\"afterend\", this.element.node);\n                }\n            }\n            catch (e) {\n                debug.error(\"closedCaption.js\", e);\n            }\n        }\n        /**\n         * 设置CC字幕\n         * @param caption CC字幕对象\n         */\n        async setCaption(caption) {\n            let data = { body: [] }; // 空字幕\n            if (caption && caption.subtitle_url) {\n                this.data[caption.subtitle_url] = this.data[caption.subtitle_url] || await xhr({\n                    url: caption.subtitle_url,\n                    responseType: \"json\",\n                    credentials: false\n                });\n                data = this.data[caption.subtitle_url] || data;\n            }\n            window.player.updateSubtitle(data); // 投喂字幕数据给播放器\n            setTimeout(() => {\n                if (window.player.getState() == \"PLAYING\") {\n                    // 刷新一次播放状态\n                    window.player.pause();\n                    window.player.play();\n                }\n            }, 1000);\n            if (caption && caption.subtitle_url) {\n                this.caption = caption; // 记忆当前字幕\n                API.bofqiMessage([\"载入字幕\", this.captions[0].lan_doc]);\n            }\n            else\n                API.bofqiMessage(\"关闭字幕\");\n        }\n    }\n    API.closedCaption = (data) => {\n        try {\n            new ClosedCaption().getCaption(data);\n        }\n        catch (e) {\n            toast.error(\"closedCaption.js\", e);\n        }\n    };\n})();\n\n//# sourceURL=API://@bilibili/dist/required/closedCaption.js";
    modules["commentLinkDetail.js"] = "/**\n * 本模块负责将评论区超链接还原为av号\n */\n(function () {\n    let timer;\n    API.observerAddedNodes((node) => {\n        if (/l_id/.test(node.id) || /reply-wrap/.test(node.className)) {\n            clearTimeout(timer);\n            timer = setTimeout(() => {\n                timer = undefined;\n                document.querySelectorAll(\".comment-jump-url\").forEach((d, i, e) => {\n                    if (d.href && !d.href.includes(d.text)) {\n                        const arr = d.href.split(\"/\");\n                        let text = arr[arr.length - 1] || arr[arr.length - 2];\n                        text.toLowerCase().startsWith(\"bv\") && (text = API.abv(text));\n                        e[i].title = d.text;\n                        e[i].text = text;\n                    }\n                });\n            }, 100);\n        }\n    });\n})();\n\n//# sourceURL=API://@bilibili/dist/required/commentLinkDetail.js";
    modules["danmakuHashId.js"] = "/**\n * 本模块负责实现反查弹幕发送者功能\n */\n(function () {\n    API.addCss(API.getModule(\"danmakuHashId.css\"));\n    class DanmakuHashId {\n        constructor(crc) {\n            this.count = 0; // 当前查询弹幕序号\n            // 设置正在查询的弹幕数量\n            DanmakuHashId.count = DanmakuHashId.count ? DanmakuHashId.count + 1 : 1;\n            // 当前查询弹幕排序\n            this.count = DanmakuHashId.count;\n            // 临时缓存已查询的 mid\n            DanmakuHashId.catch = DanmakuHashId.catch || {};\n            this.hash = crc;\n            this.mid = API.midcrc(this.hash);\n            this.getInfo();\n        }\n        async getInfo() {\n            try {\n                this.node = document.querySelector(\".bilibili-player-context-menu-container.active\");\n                if (!this.node)\n                    return setTimeout(() => { this.getInfo(); }, 100);\n                this.node = this.node.children[0];\n                let j = 0; // 找到的节点序号\n                for (let i = this.node.children.length - 1; i >= 0; i--) {\n                    if (this.node.children[i].textContent.includes(\"mid\")) {\n                        this.dm = this.node.children[i];\n                        j++;\n                        if (this.count === j)\n                            break;\n                    }\n                }\n                if (!this.dm)\n                    return setTimeout(() => { this.getInfo(); }, 100);\n                if (this.dm.tagName != \"LI\")\n                    return;\n                DanmakuHashId.catch[this.mid] = DanmakuHashId.catch[this.mid] || API.jsonCheck(await xhr({ url: API.objUrl(\"https://api.bilibili.com/x/web-interface/card\", { mid: this.mid }) }));\n                this.dm.innerHTML = '<div style=\"min-height:0px;z-index:-5;background-color: unset;\" class=\"bb-comment\"><div style=\"padding-top: 0;\" class=\"comment-list\"><div class=\"list-item\"><div class=\"reply-box\"><div style=\"padding:0px\" class=\"reply-item reply-wrap\"><div style=\"margin-left: 15px;vertical-align: middle;\" data-usercard-mid=\"' +\n                    this.mid + '\" class=\"reply-face\"><img src=\"' +\n                    DanmakuHashId.catch[this.mid].data.card.face + '@52w_52h.webp\" alt=\"\"></div><div class=\"reply-con\"><div class=\"user\" style=\"padding-bottom: 0;top: 3px;\"><a style=\"display:initial;padding: 0px;\" data-usercard-mid=\"' +\n                    this.mid + '\" href=\"//space.bilibili.com/' +\n                    this.mid + '\" target=\"_blank\" class=\"' +\n                    (DanmakuHashId.catch[this.mid].data.card.vip.vipType > 1 ? \"name vip-red-name\" : \"name\") + '\">' + DanmakuHashId.catch[this.mid].data.card.name + '</a> ' +\n                    DanmakuHashId.catch[this.mid].data.card.sex + '<a style=\"display:initial;padding: 0px;\" href=\"//www.bilibili.com/blackboard/help.html#%E4%BC%9A%E5%91%98%E7%AD%89%E7%BA%A7%E7%9B%B8%E5%85%B3\" target=\"_blank\"><i class=\"level l' +\n                    DanmakuHashId.catch[this.mid].data.card.level_info.current_level + '\"></i></a></div></div></div></div></div></div></div>';\n                DanmakuHashId.count--;\n            }\n            catch (e) {\n                DanmakuHashId.count--;\n                toast.error(\"danmakuHashId.js\", e);\n            }\n        }\n    }\n    DanmakuHashId.count = 0; // 正在查询弹幕数\n    DanmakuHashId.catch = {}; // 已查询弹幕缓存\n    window.danmakuHashId = (crc) => {\n        try {\n            const check = new DanmakuHashId(crc);\n            return `hash: ${check.hash} mid: ${check.mid}`;\n        }\n        catch (e) {\n            toast.error(\"danmakuHashId.js\", e);\n        }\n    };\n})();\n\n//# sourceURL=API://@bilibili/dist/required/danmakuHashId.js";
    modules["heartbeat.js"] = "/**\n * 本模块负责处理可能被广告屏蔽拓展误伤的视频心跳\n */\n(function () {\n    try {\n        API.xhrhook(['api.bilibili.com/x/report/web/heartbeat'], function (args) {\n            args[1] = args[1].replace('api.bilibili.com/x/report/web/heartbeat', 'api.bilibili.com/x/click-interface/web/heartbeat');\n        });\n    }\n    catch (e) {\n        toast.error(\"replyList.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/required/heartbeat.js";
    modules["infoNewNumber.js"] = "/**\n * 本模块负责修复资讯区新动态数目\n */\n(function () {\n    try {\n        API.jsonphook(['api.bilibili.com/x/web-interface/online'], function (xhr) {\n            const obj = API.urlObj(xhr.url);\n            let callback = obj.callback;\n            let call = window[callback];\n            if (call) {\n                window[callback] = function (v) {\n                    v.data && (v.data.region_count[165] = v.data.region_count[202]);\n                    return call(v);\n                };\n            }\n        });\n    }\n    catch (e) {\n        debug.error(\"replyList.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/required/infoNewNumber.js";
    modules["localMedia.js"] = "/**\n * 本模块负责实现旧版播放器载入本地视频及弹幕功能\n */\n(function () {\n    class LocalMedia {\n        constructor() {\n            this.data = { xml: [], json: [], mp4: [] };\n            this.offset = 0; // 弹幕当前偏移\n            this.keyboard = false; // 是否已绑定键盘事件\n        }\n        /**\n         * 读取文件地址\n         */\n        change(files) {\n            const file = files;\n            if (file.length === 0) {\n                return toast.warning(\"请选择本地视频或弹幕文件!\", \"视频:.mp4(且符合浏览器支持的编码)\", \"弹幕:.xml, .json\");\n            }\n            this.data = { xml: [], json: [], mp4: [] };\n            this.data = Array.from(file).reduce((d, i) => {\n                /\\.xml$/.test(i.name) && d.xml.push(i); // xml弹幕\n                /\\.json$/.test(i.name) && d.json.push(i); // json弹幕\n                /\\.mp4$/.test(i.name) && d.mp4.push(i); // mp4视频\n                return d;\n            }, this.data);\n            if (!this.data.xml[0] && !this.data.json[0] && !this.data.mp4[0]) {\n                return toast.warning(\"未能识别到任何有效文件信息 →_→\");\n            }\n            this.video();\n            this.danmaku();\n        }\n        /**\n         * 读取文件内容\n         * @param file 记录本地文件信息的 file 对象\n         */\n        readFile(file) {\n            return new Promise((resolve, reject) => {\n                if (!file)\n                    reject(toast.error('无效文件路径!'));\n                const reader = new FileReader();\n                reader.readAsText(file, 'utf-8');\n                reader.onload = () => {\n                    resolve(reader.result);\n                };\n                reader.onerror = () => {\n                    reject(toast.error('读取文件出错,请重试!'));\n                };\n            });\n        }\n        /**\n         * 载入弹幕\n         */\n        async danmaku() {\n            var _a;\n            if (!API.loadLocalDm) {\n                return toast.error(\"载入本地弹幕失败:本地弹幕组件丢失!\");\n            }\n            if (!this.data.xml[0] && !this.data.json[0])\n                return;\n            this.data.xml.forEach(async (d, i) => {\n                // 读取xml弹幕\n                let data = await this.readFile(d);\n                toast(\"本地弹幕:\" + d.name, \"载入模式:\" + ((i || config.concatDanmaku) ? \"与当前弹幕合并\" : \"替换当前弹幕\"));\n                API.loadLocalDm(data, Boolean(i) || config.concatDanmaku);\n            });\n            this.data.json.forEach(async (d, i) => {\n                var _a;\n                // 读取json弹幕\n                let data = JSON.parse(await this.readFile(d)) || [];\n                toast(\"本地弹幕:\" + d.name, \"载入模式:\" + ((this.data.xml[0] || i || config.concatDanmaku) ? \"与当前弹幕合并\" : \"替换当前弹幕\"));\n                (_a = window.player) === null || _a === void 0 ? void 0 : _a.setDanmaku(data, this.data.xml[0] || Boolean(i) || config.concatDanmaku);\n            });\n            API.bofqiMessage();\n            this.offset = 0; // 记录或重置弹幕偏移时间\n            if (!((_a = window.player) === null || _a === void 0 ? void 0 : _a.offsetDanmaku))\n                return toast.error(\"绑定键盘事件失败:弹幕偏移组件丢失!\");\n            else {\n                toast(\"已绑定键盘事件\", \"可以通过键盘 , 和 . 两个键(即上标为 < 和 > 的两个键)提前或延后弹幕偏移,频度1秒/次\");\n                if (!this.keyboard) {\n                    this.keyboard = true;\n                    document.addEventListener(\"keydown\", (ev) => {\n                        switch (ev.key) {\n                            case \",\":\n                                window.player.offsetDanmaku(-1);\n                                this.offset--;\n                                API.bofqiMessage([\"弹幕偏移:\", `${this.offset} 秒`]);\n                                break;\n                            case \".\":\n                                window.player.offsetDanmaku(1);\n                                this.offset++;\n                                API.bofqiMessage([\"弹幕偏移:\", `${this.offset} 秒`]);\n                                break;\n                            default:\n                                break;\n                        }\n                    });\n                }\n            }\n        }\n        /**\n         * 载入视频\n         */\n        video() {\n            if (this.data.mp4[0]) {\n                toast.warning(\"载入本地视频中...\", \"请无视控制台大量报错!\");\n                let video = document.querySelector(\"video\");\n                video.src = URL.createObjectURL(this.data.mp4[0]);\n                toast.success(\"本地视频:\" + this.data.mp4[0].name);\n                document.querySelector(\".bilibili-player-video-time-total\").textContent = this.time(video.duration); // 修复总时长\n            }\n        }\n        /**\n         * 格式化时间轴\n         * @param time 时间/秒\n         * @returns mm:ss\n         */\n        time(time) {\n            time = Number(time) || 0;\n            let s = time % 60;\n            let m = (time - s) / 60;\n            s = (Array(2).join('0') + s).slice(-2);\n            m = m < 10 ? (Array(2).join('0') + m).slice(-2) : m;\n            return `${m}:${s}`;\n        }\n    }\n    const localMedia = new LocalMedia();\n    API.localMedia = (files) => {\n        try {\n            localMedia.change(files);\n        }\n        catch (e) {\n            toast.error(\"localMedia.js\", e);\n        }\n    };\n})();\n\n//# sourceURL=API://@bilibili/dist/required/localMedia.js";
    modules["logReport.js"] = "/**\n * 本模块负责拦截B站各种日志上报\n */\n(function () {\n    class Over {\n        static block(para, target = window) {\n            Object.defineProperty(target, para, { get: () => Over.temp, set: () => true });\n        }\n    }\n    Over.temp = new Proxy(() => true, { get: () => Over.temp });\n    Over.block(\"__statisObserver\"); // 直播间日志\n    Over.block(\"__tempPvTracker\"); // 直播间日志\n    API.xhrhook([\"data.bilibili.com\"], function (args) { this.send = () => true; });\n    API.xhrhook([\"data.bilivideo.com\"], function (args) { this.send = () => true; });\n})();\n\n//# sourceURL=API://@bilibili/dist/required/logReport.js";
    modules["noVideo.js"] = "/**\n * 本模块负责强制拦截视频载入\n */\n(function () {\n    try {\n        API.xhrhook([\"/playurl?\"], function (args) {\n            let obj = API.urlObj(args[1]);\n            obj.aid = 1, obj.cid = 1, obj.ep_id = 1;\n            args[1] = API.objUrl(args[1].split(\"?\")[0], obj);\n        });\n        API.switchVideo(() => {\n            API.bofqiMessage([\"拦截视频页媒体载入用于呼出下载面板\", \"取消拦截\"], 3, () => {\n                config.noVideo = false;\n                window.BilibiliPlayer({ aid: API.aid, cid: API.cid });\n            }, true);\n        });\n    }\n    catch (e) {\n        debug.error(\"noVideo.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/required/noVideo.js";
    modules["parameterTrim.js"] = "/**\n * 本模块负责处理URL,包括地址栏和a标签\n */\n(function () {\n    try {\n        class ParameterTrim {\n            constructor() {\n                /**\n                 * 过滤参数\n                 */\n                this.param = {\n                    \"spm_id_from\": null,\n                    \"from_source\": null,\n                    \"msource\": null,\n                    \"bsource\": null,\n                    \"seid\": null,\n                    \"source\": null,\n                    \"session_id\": null,\n                    \"visit_id\": null,\n                    \"sourceFrom\": null,\n                    \"from_spmid\": null,\n                    \"share_source\": null,\n                    \"share_medium\": null,\n                    \"share_plat\": null,\n                    \"share_session_id\": null,\n                    \"share_tag\": null,\n                    \"unique_k\": null,\n                };\n                /**\n                 * 地址变动参考\n                 */\n                this.url = [];\n            }\n            /**\n             * 地址栏\n             */\n            location() {\n                this.url[1] = location.href; // 暂存URL,以便比较URL变化\n                if (this.url[0] != this.url[1]) {\n                    let href = this.triming(location.href); // 处理链接\n                    window.history.replaceState(null, \"\", href); // 推送到地址栏\n                    this.url[0] = location.href; // 刷新暂存\n                }\n            }\n            /**\n             * 处理a标签\n             * @param list a标签集\n             */\n            anchor(list) {\n                list.forEach((d) => {\n                    if (!d.href)\n                        return;\n                    d.href.includes(\"bilibili.tv\") && (d.href = d.href.replace(\"bilibili.tv\", \"bilibili.com\"));\n                    d.href.includes(\"www.bilibili.com/tag\") && (d.href = d.href.replace(\"tag\", \"topic\"));\n                    d.href.includes(\"account.bilibili.com/login?act=exit\") && (d.href = \"javascript:void(0);\", d.onclick = () => API.loginExit());\n                    (!/^.+:/.test(d.href) || /^(https?:)?\\/\\//.test(d.href)) && (d.href = this.triming(d.href));\n                });\n            }\n            /**\n             * 处理引导\n             * @param url 源URL\n             * @returns URL\n             */\n            triming(url) {\n                let obj = this.search(url);\n                url = this.hash(url);\n                return API.objUrl(url, obj);\n            }\n            /**\n             * 处理查询参数部分\n             * @param url 源URL\n             * @returns 参数对象\n             */\n            search(url) {\n                let obj = API.urlObj(url);\n                obj.bvid && (obj.aid = API.abv(obj.bvid)); // 存在bvid,添加aid\n                obj.aid && !Number(obj.aid) && (obj.aid = API.abv(obj.aid)); // aid误为bvid,转化\n                (obj.from && obj.from == \"search\") && (obj.from = null);\n                obj = { ...obj, ...this.param };\n                return obj;\n            }\n            /**\n             * 处理非查询部分\n             * @param url 源URL\n             * @returns URL\n             */\n            hash(url) {\n                let hash = url.includes(\"#\") ? `#${url.split(\"#\")[1]}` : \"\";\n                hash.includes(\"?\") && (hash = hash.split(\"?\")[0]);\n                let arr = url.split(\"#\")[0].split(\"?\")[0].split(\"/\"); // 分割URL\n                arr.forEach((d, i, e) => {\n                    (d.toLowerCase().startsWith('bv')) && (e[i] = \"av\" + API.abv(d));\n                });\n                return arr.join(\"/\") + hash;\n            }\n            click(e) {\n                var f = e.target;\n                for (; f && \"A\" !== f.tagName;) {\n                    f = f.parentNode;\n                }\n                if (\"A\" !== (null == f ? void 0 : f.tagName)) {\n                    return;\n                }\n                f.href && (f.href = this.triming(f.href));\n            }\n        }\n        const parameterTrim = new ParameterTrim();\n        // @ts-ignore 重写标记\n        if (Before)\n            return parameterTrim.location();\n        API.switchVideo(() => { parameterTrim.location(); });\n        API.observerAddedNodes(async (node) => {\n            node.querySelectorAll && parameterTrim.anchor(node.querySelectorAll(\"a\"));\n            node.tagName == \"A\" && parameterTrim.anchor([node]);\n        });\n        document.addEventListener(\"click\", e => parameterTrim.click(e), !1);\n    }\n    catch (e) {\n        debug.error(\"parameterTrim.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/required/parameterTrim.js";
    modules["player-v2.js"] = "/**\n * 本模块负责获取视频信息以提供给CC字幕等模块\n * 视频信息接口`https://api.bilibili.com/x/player/v2`\n * 备用移动端接口`https://api.bilibili.com/x/v2/dm/view`\n */\n(function () {\n    try {\n        API.switchVideo(() => {\n            let ready = false; // 载入时机标记\n            API.xhrhook([\"api.bilibili.com/x/player/carousel.so\"], function (args) { ready = true; });\n            xhr({\n                url: API.objUrl(\"https://api.bilibili.com/x/player/v2\", { cid: API.cid, aid: API.aid }),\n                responseType: \"json\",\n                credentials: true\n            }).catch((e) => {\n                debug.error(\"autoFix.js\", e);\n                return xhr({\n                    url: API.objUrl(\"https://api.bilibili.com/x/v2/dm/view\", { oid: API.cid, aid: API.aid, type: 1 }),\n                    responseType: \"json\",\n                    credentials: true\n                });\n            }).then((data) => {\n                API.runWhile(() => ready, () => {\n                    var _a, _b, _c;\n                    // CC字幕\n                    ((_b = (_a = data === null || data === void 0 ? void 0 : data.data) === null || _a === void 0 ? void 0 : _a.subtitle) === null || _b === void 0 ? void 0 : _b.subtitles) && API.closedCaption(data);\n                    // 分段进度条\n                    config.segProgress && ((_c = data === null || data === void 0 ? void 0 : data.data) === null || _c === void 0 ? void 0 : _c.view_points[1]) && API.segProgress(data);\n                });\n            });\n        });\n    }\n    catch (e) {\n        toast.error(\"player-v2.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/required/player-v2.js";
    modules["playinfoRecord.js"] = "/**\n * 本模块负责处理并记录playinfo信息\n */\n(function () {\n    API.xhrhook([\"/playurl?\"], function (args) {\n        let obj = API.urlObj(args[1]);\n        !obj.sign && (obj.fourk = 1, obj.fnval && (obj.fnval = 2000)); // 8K支持\n        obj.avid && Number(obj.avid) && Reflect.set(API, \"aid\", obj.avid);\n        !API.aid && obj.bvid && Reflect.set(API, \"aid\", API.abv(obj.bvid));\n        obj.cid && Number(obj.cid) && Reflect.set(API, \"cid\", obj.cid);\n        args[1] = API.objUrl(args[1].split(\"?\")[0], obj); // 还原URL\n        args[1].includes(\"84956560bc028eb7\") && (args[1] = API.urlsign(args[1], {}, 8)); // 过滤无效key\n        args[1].includes(\"pgc\") && (API.pgc = true);\n        this.addEventListener(\"readystatechange\", async () => record.call(this));\n    });\n    function record() {\n        try {\n            if (this.readyState === 4) {\n                if (!this.response)\n                    throw this;\n                API.__playinfo__ = typeof this.response == \"object\" ? this.response : API.jsonCheck(this.response);\n            }\n        }\n        catch (e) {\n            debug.error(\"playinfoRecord.js\", e);\n        }\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/required/playinfoRecord.js";
    modules["protoDm.js"] = "/**\n * 本模块负责使旧版播放器支持新版弹幕\n */\n(function () {\n    try {\n        // 修复一般弹幕\n        API.importModule(\"worker.js\");\n        // 修复历史弹幕\n        let id = API.xhrhook([\"history?type=\"], function (args) {\n            var _a;\n            if (!((_a = window.player) === null || _a === void 0 ? void 0 : _a.setDanmaku)) {\n                API.removeXhrhook(id);\n                return toast.warning(\"内部组件丢失!\");\n            }\n            let param = API.urlObj(args[1]);\n            if (param.date) {\n                Object.defineProperty(this, \"response\", { writable: true });\n                Object.defineProperty(this, \"readyState\", { writable: true });\n                Object.defineProperty(this, \"status\", { writable: true });\n                Object.defineProperty(this, \"send\", { writable: true });\n                this.readyState = 4;\n                this.status = 200;\n                this.send = () => { };\n                let history = \"https://api.bilibili.com/x/v2/dm/web/history/seg.so?type=1&oid=\" + API.cid + \"&date=\" + param.date;\n                xhr({\n                    url: history,\n                    responseType: \"arraybuffer\",\n                    credentials: true\n                }).then((seg) => {\n                    var _a;\n                    let segDm = API.segDmDecode(seg);\n                    (_a = window.player) === null || _a === void 0 ? void 0 : _a.setDanmaku(API.danmaku = API.danmakuFormat(segDm));\n                }).catch((e) => {\n                    toast.error(\"载入历史弹幕失败\", \"请尝试刷新页面\");\n                    toast.error(e);\n                });\n            }\n        });\n    }\n    catch (e) {\n        toast.error(\"protoDm.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/required/protoDm.js";
    modules["rebuildPlayerurl.js"] = "/**\n * 本模块负责重建playurl为网页端类型\n */\n(function () {\n    try {\n        const OBJ = {};\n        class RebuildPlayerurl {\n            constructor() {\n                this.playurl = {\n                    accept_description: [\"高清 1080P+\", \"高清 1080P\", \"高清 720P\", \"清晰 480P\", \"流畅 360P\"],\n                    accept_format: \"hdflv2,flv,flv720,flv480,mp4\",\n                    accept_quality: [112, 80, 64, 32, 16],\n                    bp: 0,\n                    code: 0,\n                    dash: {\n                        audio: [],\n                        dolby: { audio: [], type: \"NONE\" },\n                        duration: 0,\n                        min_buffer_time: 1.5,\n                        minBufferTime: 1.5,\n                        video: []\n                    },\n                    fnval: 0,\n                    fnver: 0,\n                    format: \"flv480\",\n                    from: \"local\",\n                    has_paid: false,\n                    is_preview: 0,\n                    message: \"\",\n                    no_rexcode: 1,\n                    quality: 32,\n                    result: \"suee\",\n                    seek_param: \"start\",\n                    seek_type: \"offset\",\n                    status: 2,\n                    support_formats: [\n                        {\n                            description: \"高清 1080P+\",\n                            display_desc: \"1080P\",\n                            format: \"hdflv2\",\n                            need_login: true,\n                            need_vip: true,\n                            new_description: \"1080P 高码率\",\n                            quality: 112,\n                            superscript: \"高码率\"\n                        },\n                        {\n                            description: \"高清 1080P\",\n                            display_desc: \"1080P\",\n                            format: \"flv\",\n                            need_login: true,\n                            new_description: \"1080P 高清\",\n                            quality: 80,\n                            superscript: \"\"\n                        },\n                        {\n                            description: \"高清 720P\",\n                            display_desc: \"720P\",\n                            format: \"flv720\",\n                            need_login: true,\n                            new_description: \"720P 高清\",\n                            quality: 64,\n                            superscript: \"\"\n                        },\n                        {\n                            description: \"清晰 480P\",\n                            display_desc: \"480P\",\n                            format: \"flv480\",\n                            new_description: \"480P 清晰\",\n                            quality: 32,\n                            superscript: \"\"\n                        },\n                        {\n                            description: \"流畅 360P\",\n                            display_desc: \"360P\",\n                            format: \"mp4\",\n                            new_description: \"360P 流畅\",\n                            quality: 16,\n                            superscript: \"\"\n                        }\n                    ],\n                    timelength: 0,\n                    type: \"DASH\",\n                    video_codecid: 7,\n                    video_project: true\n                };\n                this.codecs = {\n                    default: {\n                        30112: 'avc1.640028',\n                        30102: 'hev1.1.6.L120.90',\n                        30080: 'avc1.640028',\n                        30077: 'hev1.1.6.L120.90',\n                        30064: 'avc1.64001F',\n                        30066: 'hev1.1.6.L120.90',\n                        30032: 'avc1.64001E',\n                        30033: 'hev1.1.6.L120.90',\n                        30011: 'hev1.1.6.L120.90',\n                        30016: 'avc1.64001E',\n                        30280: 'mp4a.40.2',\n                        30232: 'mp4a.40.2',\n                        30216: 'mp4a.40.2', // 低码音频\n                    },\n                    app: {\n                        30016: 'avc1.64001E',\n                        30032: 'avc1.64001F',\n                        30064: 'avc1.640028',\n                        30080: 'avc1.640032',\n                        30216: 'mp4a.40.2',\n                        30232: 'mp4a.40.2',\n                        30280: 'mp4a.40.2' // APP源 高码音频 \n                    }\n                };\n                this.frameRate = {\n                    30112: '16000/672',\n                    30102: '16000/672',\n                    30080: '16000/672',\n                    30077: '16000/656',\n                    30064: '16000/672',\n                    30066: '16000/656',\n                    30032: '16000/672',\n                    30033: '16000/656',\n                    30011: '16000/656',\n                    30016: '16000/672'\n                };\n                this.resolution = {\n                    30112: [1920, 1080],\n                    30102: [1920, 1080],\n                    30080: [1920, 1080],\n                    30077: [1920, 1080],\n                    30064: [1280, 720],\n                    30066: [1280, 720],\n                    30032: [852, 480],\n                    30033: [852, 480],\n                    30011: [640, 360],\n                    30016: [640, 360], // 360P\n                };\n            }\n            /**\n             * 获取链接ids\n             * @param url 下载链接\n             * @param duration 媒体时长\n             */\n            getIdxs(url, duration) {\n                let range = Math.round(duration * 3.5);\n                range = range < 6000 ? 6000 : range;\n                return xhr({\n                    url: url,\n                    responseType: 'arraybuffer',\n                    headers: { 'Range': `bytes=0-${range}` },\n                    credentials: false\n                });\n            }\n            /**\n             * 过滤问题音频\n             * @param audio 音频数据数组\n             */\n            fixAudio(audio) {\n                return audio.reduce((arr, d) => {\n                    if (d.id == 30232 || d.id == 30280 || d.id == 30216)\n                        arr.push(d);\n                    return arr;\n                }, []);\n            }\n            /**\n             * 重构APP端数据\n             * @param app 原始数据对象\n             */\n            async appPlayurl(app) {\n                if (app.durl)\n                    return app;\n                if (app.dash.duration) {\n                    app.dash.audio = this.fixAudio(app.dash.audio);\n                    return app;\n                }\n                toast(\"重构DASH数据中...\");\n                for (let key in app)\n                    this.playurl[key] = app[key];\n                // duration向上取整\n                this.playurl.dash.duration = Math.ceil(app.timelength / 1000);\n                this.playurl.dash.minBufferTime = this.playurl.dash.min_buffer_time = 1.5;\n                // 构造Promise序列以同时获取所有DASH媒体segment数据\n                // 本应由播放器自行获取,B站官方称之为【首帧优化】却在缺失时直接报错导致播放器无法正常载入视频\n                let arr = [];\n                this.playurl.dash.video.forEach((d, i, e) => {\n                    arr.push((async (d) => {\n                        OBJ[\"sidx\" + String(API.cid)] = OBJ[\"sidx\" + String(API.cid)] || {};\n                        let id = d.base_url.match(/[0-9]+\\.m4s/)[0].split(\".\")[0];\n                        if (d.SegmentBase)\n                            OBJ[\"sidx\" + String(API.cid)][id] = [d.SegmentBase.Initialization, d.SegmentBase.indexRange];\n                        if (!OBJ[\"sidx\" + String(API.cid)][id]) {\n                            let data = new Uint8Array(await this.getIdxs(d.base_url, this.playurl.dash.duration));\n                            let hex_data = Array.prototype.map.call(data, x => ('00' + x.toString(16)).slice(-2)).join('');\n                            // 首个“sidx”出现4字节之前的部分为索引起始点\n                            let indexRangeStart = hex_data.indexOf('73696478') / 2 - 4;\n                            // 首个“mooc”出现前5字节结束索引\n                            let indexRagneEnd = hex_data.indexOf('6d6f6f66') / 2 - 5;\n                            // 挂载到BLOD下,切换清晰度直接继承使用(以cid为切p标记)\n                            OBJ[\"sidx\" + String(API.cid)][id] = ['0-' + String(indexRangeStart - 1), String(indexRangeStart) + '-' + String(indexRagneEnd)];\n                            debug(\"DASH-video:\", id, OBJ[\"sidx\" + String(API.cid)][id]);\n                        }\n                        d.segment_base = {\n                            initialization: OBJ[\"sidx\" + String(API.cid)][id][0],\n                            index_range: OBJ[\"sidx\" + String(API.cid)][id][1]\n                        };\n                        d.SegmentBase = {\n                            Initialization: OBJ[\"sidx\" + String(API.cid)][id][0],\n                            indexRange: OBJ[\"sidx\" + String(API.cid)][id][1]\n                        };\n                        d.backupUrl = d.backup_url = d.backupUrl || d.backup_url || [];\n                        d.baseUrl = d.base_url;\n                        d.codecs = d.codecs || this.codecs.app[id] || this.codecs.default[id];\n                        d.frameRate = d.frame_rate = d.frameRate || d.frame_rate || this.frameRate[id];\n                        d.height = d.height || this.resolution[id][1];\n                        d.width = d.width || this.resolution[id][0];\n                        d.mimeType = d.mime_type = d.mimeType || d.mime_type || 'video/mp4';\n                        d.sar = d.sar || \"1:1\";\n                        d.startWithSAP = d.start_with_sap = d.startWithSAP || d.start_with_sap || 1;\n                    })(e[i]));\n                });\n                this.playurl.dash.audio = this.fixAudio(this.playurl.dash.audio);\n                this.playurl.dash.audio.forEach((d, i, e) => {\n                    arr.push((async (d) => {\n                        OBJ[\"sidx\" + String(API.cid)] = OBJ[\"sidx\" + String(API.cid)] || {};\n                        let id = d.base_url.match(/[0-9]+\\.m4s/)[0].split(\".\")[0];\n                        if (d.SegmentBase)\n                            OBJ[\"sidx\" + String(API.cid)][id] = [d.SegmentBase.Initialization, d.SegmentBase.indexRange];\n                        if (!OBJ[\"sidx\" + String(API.cid)][id]) {\n                            let data = new Uint8Array(await this.getIdxs(d.base_url, this.playurl.dash.duration));\n                            let hex_data = Array.prototype.map.call(data, x => ('00' + x.toString(16)).slice(-2)).join('');\n                            let indexRangeStart = hex_data.indexOf('73696478') / 2 - 4;\n                            let indexRagneEnd = hex_data.indexOf('6d6f6f66') / 2 - 5;\n                            OBJ[\"sidx\" + String(API.cid)][id] = ['0-' + String(indexRangeStart - 1), String(indexRangeStart) + '-' + String(indexRagneEnd)];\n                            debug(\"DASH-audio:\", id, OBJ[\"sidx\" + String(API.cid)][id]);\n                        }\n                        d.segment_base = {\n                            initialization: OBJ[\"sidx\" + String(API.cid)][id][0],\n                            index_range: OBJ[\"sidx\" + String(API.cid)][id][1]\n                        };\n                        d.SegmentBase = {\n                            Initialization: OBJ[\"sidx\" + String(API.cid)][id][0],\n                            indexRange: OBJ[\"sidx\" + String(API.cid)][id][1]\n                        };\n                        d.backupUrl = d.backup_url = d.backupUrl || d.backup_url || [];\n                        d.baseUrl = d.base_url;\n                        d.codecs = d.codecs || this.codecs.app[id] || this.codecs.default[id] || \"mp4a.40.2\";\n                        d.mimeType = d.mime_type = d.mimeType || d.mime_type || 'audio/mp4';\n                    })(e[i]));\n                });\n                toast(\"等待数据回传...\");\n                if (arr[0])\n                    await Promise.all(arr);\n                // video排序\n                let avc = [], hev = [], video = [];\n                this.playurl.dash.video.forEach((d) => {\n                    if (d.codecid == 7)\n                        avc.push(d);\n                    else\n                        hev.push(d);\n                });\n                let length = avc.length > hev.length ? avc.length : hev.length;\n                for (let i = length - 1; i >= 0; i--) {\n                    if (avc[i])\n                        video.push(avc[i]);\n                    if (hev[i])\n                        video.push(hev[i]);\n                }\n                this.playurl.dash.video = video;\n                toast.success(\"DASH数据重构成功!\", \"正在投喂给播放器...\");\n                debug.log(this.playurl);\n                return this.playurl;\n            }\n            /**\n             * 重构Thailand数据\n             * @param ogv 原始数据\n             */\n            async ogvPlayurl(ogv) {\n                toast(\"重构DASH数据中...\");\n                this.playurl.quality = ogv.data.video_info.quality;\n                let num = this.playurl.accept_quality.indexOf(this.playurl.quality);\n                this.playurl.format = this.playurl.accept_format.split(\",\")[num];\n                this.playurl.timelength = ogv.data.video_info.timelength;\n                this.playurl.accept_quality.splice(0, num);\n                this.playurl.support_formats.splice(0, num);\n                this.playurl.accept_description.splice(0, num);\n                this.playurl.accept_format = this.playurl.accept_format.split(\",\");\n                this.playurl.accept_format.splice(0, num);\n                this.playurl.accept_format = this.playurl.accept_format.join(\",\");\n                this.playurl.dash.duration = Math.ceil(this.playurl.timelength / 1000);\n                this.playurl.dash.minBufferTime = this.playurl.dash.min_buffer_time = 1.5;\n                let arr = [];\n                ogv.data.video_info.stream_list.forEach((d) => {\n                    if (d.dash_video && d.dash_video.base_url) {\n                        arr.push((async (d) => {\n                            OBJ[\"sidx\" + String(API.cid)] = OBJ[\"sidx\" + String(API.cid)] || {};\n                            let id = d.dash_video.base_url.match(/[0-9]+\\.m4s/)[0].split(\".\")[0];\n                            if (!OBJ[\"sidx\" + String(API.cid)][id]) {\n                                let data = new Uint8Array(await this.getIdxs(d.dash_video.base_url, this.playurl.dash.duration));\n                                let hex_data = Array.prototype.map.call(data, x => ('00' + x.toString(16)).slice(-2)).join('');\n                                let indexRangeStart = hex_data.indexOf('73696478') / 2 - 4;\n                                let indexRagneEnd = hex_data.indexOf('6d6f6f66') / 2 - 5;\n                                OBJ[\"sidx\" + String(API.cid)][id] = ['0-' + String(indexRangeStart - 1), String(indexRangeStart) + '-' + String(indexRagneEnd)];\n                                debug(\"DASH-video:\", id, OBJ[\"sidx\" + String(API.cid)][id]);\n                            }\n                            this.playurl.dash.video.push({\n                                SegmentBase: {\n                                    Initialization: OBJ[\"sidx\" + String(API.cid)][id][0],\n                                    indexRange: OBJ[\"sidx\" + String(API.cid)][id][1]\n                                },\n                                segment_base: {\n                                    initialization: OBJ[\"sidx\" + String(API.cid)][id][0],\n                                    index_range: OBJ[\"sidx\" + String(API.cid)][id][1]\n                                },\n                                backupUrl: [],\n                                backup_url: [],\n                                bandwidth: d.dash_video.bandwidth,\n                                baseUrl: d.dash_video.base_url,\n                                base_url: d.dash_video.base_url,\n                                codecid: d.dash_video.codecid,\n                                codecs: this.codecs.app[id] || this.codecs.default[id],\n                                frameRate: this.frameRate[id],\n                                frame_rate: this.frameRate[id],\n                                height: this.resolution[id][1],\n                                id: d.stream_info.quality,\n                                md5: d.dash_video.md5,\n                                mimeType: \"video/mp4\",\n                                mime_type: \"video/mp4\",\n                                sar: \"1:1\",\n                                size: d.dash_video.size,\n                                startWithSAP: 1,\n                                start_with_sap: 1,\n                                width: this.resolution[id][0]\n                            });\n                        })(d));\n                    }\n                })(ogv.data.video_info.dash_audio).forEach((d) => {\n                    arr.push((async (d) => {\n                        OBJ[\"sidx\" + String(API.cid)] = OBJ[\"sidx\" + String(API.cid)] || {};\n                        let id = d.base_url.match(/[0-9]+\\.m4s/)[0].split(\".\")[0];\n                        if (!OBJ[\"sidx\" + String(API.cid)][id]) {\n                            let data = new Uint8Array(await this.getIdxs(d.base_url, this.playurl.dash.duration));\n                            let hex_data = Array.prototype.map.call(data, x => ('00' + x.toString(16)).slice(-2)).join('');\n                            let indexRangeStart = hex_data.indexOf('73696478') / 2 - 4;\n                            let indexRagneEnd = hex_data.indexOf('6d6f6f66') / 2 - 5;\n                            OBJ[\"sidx\" + String(API.cid)][id] = ['0-' + String(indexRangeStart - 1), String(indexRangeStart) + '-' + String(indexRagneEnd)];\n                            debug(\"DASH-audio:\", id, OBJ[\"sidx\" + String(API.cid)][id]);\n                        }\n                        this.playurl.dash.audio.push({\n                            SegmentBase: {\n                                Initialization: OBJ[\"sidx\" + String(API.cid)][id][0],\n                                indexRange: OBJ[\"sidx\" + String(API.cid)][id][1]\n                            },\n                            segment_base: {\n                                initialization: OBJ[\"sidx\" + String(API.cid)][id][0],\n                                index_range: OBJ[\"sidx\" + String(API.cid)][id][1]\n                            },\n                            backupUrl: [],\n                            backup_url: [],\n                            bandwidth: d.bandwidth,\n                            baseUrl: d.base_url,\n                            base_url: d.base_url,\n                            codecid: d.codecid,\n                            codecs: this.codecs.app[id] || this.codecs.default[id],\n                            frameRate: \"\",\n                            frame_rate: \"\",\n                            height: 0,\n                            id: id,\n                            md5: d.md5,\n                            mimeType: \"audio/mp4\",\n                            mime_type: \"audio/mp4\",\n                            sar: \"\",\n                            size: d.size,\n                            startWithSAP: 0,\n                            start_with_sap: 0,\n                            width: 0\n                        });\n                    })(d));\n                });\n                toast(\"等待数据回传...\");\n                await Promise.all(arr);\n                toast.success(\"DASH数据重构成功!\", \"正在投喂给播放器...\");\n                debug.log(this.playurl);\n                return this.playurl;\n            }\n        }\n        API.RebuildPlayerurl = RebuildPlayerurl;\n    }\n    catch (e) {\n        toast.error(\"rebuildPlayerurl.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/required/rebuildPlayerurl.js";
    modules["replyList.js"] = "/**\n * 本模块负责恢复翻页评论区\n */\n(function () {\n    try {\n        API.scriptIntercept([\"comment.min.js\"], \"https://cdn.jsdelivr.net/gh/MotooriKashin/Bilibili-Old/dist/comment.min.js\");\n        class ReplyList {\n            init() {\n                // 拦截评论脚本\n                if (window.bbComment)\n                    return this.cover(); // 评论已载入直接覆盖\n                // 监听评论脚本载入并覆盖\n                Object.defineProperty(window, \"bbComment\", {\n                    set: () => { this.cover(); },\n                    get: () => undefined,\n                    configurable: true\n                });\n            }\n            cover() {\n                delete window.bbComment; // 取消拦截\n                new Function(GM.getResourceText(config.oldReplySort ? \"comment.min.js\" : \"comment.js\"))(); // 载入旧版脚本\n                API.addElement(\"link\", { href: \"//static.hdslb.com/phoenix/dist/css/comment.min.css\", rel: \"stylesheet\" }, document.head);\n                API.addCss(API.getCss(\"comment.css\"));\n                config.oldReplySort && API.addCss(API.getCss(\"oldReplySort.css\"));\n                this.style();\n            }\n            async style() {\n                const arr = document.querySelectorAll(\"style\");\n                arr.forEach((d, i) => {\n                    d.outerHTML.includes(\"/*热门评论分割线*/\") && arr[i].remove();\n                });\n            }\n        }\n        new ReplyList().init();\n        API.jsonphook([\"api.bilibili.com/x/v2/reply?\"], (xhr) => {\n            !xhr.url.includes(\"mobi_app\") && (xhr.url += `&mobi_app=android`);\n        });\n        config.commentLinkDetail && API.importModule(\"commentLinkDetail.js\");\n    }\n    catch (e) {\n        toast.error(\"replyList.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/required/replyList.js";
    modules["section.js"] = "/**\n * 本模块负责替换全局顶栏和底栏\n */\n(function () {\n    try {\n        API.runWhile(() => document.querySelector(\"#internationalHeader\"), () => {\n            var _a;\n            if (API.path.name)\n                return;\n            API.addCss(\".nav-item.live {width: auto;}\");\n            document.querySelector(\"#internationalHeader\").setAttribute(\"style\", \"visibility:hidden;\");\n            (!((_a = window.$) === null || _a === void 0 ? void 0 : _a.ajax)) && API.addElement(\"script\", { type: \"text/javascript\", src: \"//static.hdslb.com/js/jquery.min.js\" }, undefined, undefined, true);\n            (document.querySelector(\".mini-type\") && !location.href.includes(\"blackboard/topic_list\") && !location.href.includes(\"blackboard/x/act_list\")) ? API.addElement(\"div\", { class: \"z-top-container\" }, undefined, undefined, true) : API.addElement(\"div\", { class: \"z-top-container has-menu\" }, undefined, undefined, true);\n            API.addElement(\"script\", { type: \"text/javascript\", src: \"//s1.hdslb.com/bfs/seed/jinkela/header/header.js\" });\n        });\n        API.runWhile(() => document.querySelector(\".international-footer\"), () => {\n            var _a;\n            if (API.path.name)\n                return;\n            document.querySelector(\".international-footer\").remove();\n            (!((_a = window.$) === null || _a === void 0 ? void 0 : _a.ajax)) && API.addElement(\"script\", { type: \"text/javascript\", src: \"//static.hdslb.com/js/jquery.min.js\" }, undefined, undefined, true);\n            API.addElement(\"div\", { class: \"footer bili-footer report-wrap-module\", id: \"home_footer\" });\n            API.addElement(\"script\", { type: \"text/javascript\", src: \"//static.hdslb.com/common/js/footer.js\" });\n        });\n        API.runWhile(() => document.querySelector(\"#bili-header-m\"), () => {\n            var _a;\n            (_a = document.querySelector(\"#internationalHeader\")) === null || _a === void 0 ? void 0 : _a.remove();\n            API.addCss(API.getModule(\"avatarAnimation.css\"));\n        });\n    }\n    catch (e) {\n        debug.error(\"section.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/required/section.js";
    modules["sectionTypo.js"] = "/**\n * 本模块负责修正旧版顶栏分区\n */\n(function () {\n    API.runWhile(() => document.querySelector(\"#bili-header-m\"), () => {\n        try {\n            let node = document.querySelector(\"#bili-header-m\").getElementsByClassName('nav-name');\n            if (node[0]) {\n                for (let i = 0; i < node.length; i++) {\n                    if (node[i].textContent == \"科技\") {\n                        node[i].textContent = \"知识\";\n                        node[i].parentNode.href = \"//www.bilibili.com/v/knowledge/\";\n                        node[i].parentNode.parentNode.children[1].innerHTML = `<li><a href=\"//www.bilibili.com/v/knowledge/science/\"><span>科学科普</span></a></li>\n                        <li><a href=\"//www.bilibili.com/v/knowledge/social_science/\"><span>社科·法律·心理</span></a></li>\n                        <li><a href=\"//www.bilibili.com/v/knowledge/humanity_history/\"><span>人文历史</span></a></li>\n                        <li><a href=\"//www.bilibili.com/v/knowledge/business/\"><span>财经商业</span></a></li>\n                        <li><a href=\"//www.bilibili.com/v/knowledge/campus/\"><span>校园学习</span></a></li>\n                        <li><a href=\"//www.bilibili.com/v/knowledge/career/\"><span>职业职场</span></a></li>\n                        <li><a href=\"//www.bilibili.com/v/knowledge/design/\"><span>设计·创意</span></a></li>\n                        <li><a href=\"//www.bilibili.com/v/knowledge/skill/\"><span>野生技能协会</span></a></li>`;\n                    }\n                    if (node[i].textContent == \"数码\") {\n                        node[i].textContent = \"科技\";\n                        node[i].parentNode.href = \"//www.bilibili.com/v/tech/\";\n                        node[i].parentNode.parentNode.children[1].innerHTML = `<li><a href=\"//www.bilibili.com/v/tech/digital/\"><span>数码</span></a></li>\n                        <li><a href=\"//www.bilibili.com/v/tech/application/\"><span>软件应用</span></a></li>\n                        <li><a href=\"//www.bilibili.com/v/tech/computer_tech/\"><span>计算机技术</span></a></li>\n                        <li><a href=\"//www.bilibili.com/v/tech/industry/\"><span>工业·工程·机械</span></a></li>\n                        <li><a href=\"//www.bilibili.com/v/tech/diy/\"><span>极客DIY</span></a></li>`;\n                    }\n                    if (node[i].textContent == \"时尚\") {\n                        node[i].parentNode.parentNode.children[1].innerHTML = `<li><a href=\"//www.bilibili.com/v/fashion/makeup/\"><span>美妆护肤</span></a></li>\n                        <li><a href=\"//www.bilibili.com/v/fashion/clothing/\"><span>穿搭</span></a></li>\n                        <li><a href=\"//www.bilibili.com/v/fashion/trend/\"><span>时尚潮流</span></a></li>`;\n                    }\n                    if (node[i].textContent == \"广告\") {\n                        node[i].textContent = \"资讯\";\n                        node[i].parentNode.href = \"//www.bilibili.com/v/information/\";\n                        node[i].parentNode.parentNode.children[1].innerHTML = `<li><a href=\"//www.bilibili.com/v/information/hotspot/\"><span>热点</span></a></li>\n                        <li><a href=\"//www.bilibili.com/v/information/global/\"><span>环球</span></a></li>\n                        <li><a href=\"//www.bilibili.com/v/information/social/\"><span>社会</span></a></li>\n                        <li><a href=\"//www.bilibili.com/v/information/multiple/\"><span>综合</span></a></li>`;\n                    }\n                    if (node[i].textContent == \"生活\") {\n                        node[i].parentNode.parentNode.children[1].children[2].remove(); // 移除美食圈\n                        node[i].parentNode.parentNode.children[1].children[2].remove(); // 移除美食圈\n                        node[i].parentNode.parentNode.children[1].children[5].remove(); // 移除其他\n                        node[i].parentNode.parentNode.children[1].children[4].children[0].href = \"//www.bilibili.com/v/sports\"; // 修复运动区链接\n                    }\n                    if (node[i].textContent == \"娱乐\")\n                        node[i].parentNode.parentNode.children[1].lastChild.remove();\n                }\n            }\n        }\n        catch (e) {\n            debug.error(\"sectionTypo.js\", e);\n        }\n    });\n})();\n\n//# sourceURL=API://@bilibili/dist/required/sectionTypo.js";
    modules["segProgress.js"] = "/**\n * 本模块负责添加分段进度条\n */\n(function () {\n    class SegProgress {\n        constructor(resp) {\n            if (!resp.data.view_points || resp.data.view_points.length == 0)\n                return;\n            this.init(resp.data.view_points);\n        }\n        async init(view_points) {\n            if (!SegProgress.cssInited) {\n                SegProgress.cssInited = true;\n                API.addCss(`\n                            .bilibili-progress-segmentation-logo{display:inline-block;position:absolute;top:-12px;height:30px;width:1px}\n                            .bilibili-progress-segmentation-logo>img{position: absolute;top:-14px;transform:translate(-50%,-50%) scale(0.7);left:50%;transition:top 0.1s}\n                            .bilibili-player.mode-widescreen .bilibili-progress-segmentation-logo>img,\n                            .bilibili-player.mode-webfullscreen .bilibili-progress-segmentation-logo>img,\n                            .bilibili-player.mode-fullscreen .bilibili-progress-segmentation-logo>img{top:-18px;left:50%;transform:translate(-50%,-50%) scale(1)}\n                            .bilibili-progress-segmentation-logo.active>img#segmentation-logo{top:-110px}\n                            .bilibili-progress-segmentation{height:29px;position:absolute;top:-12px}\n                            .bilibili-progress-segmentation:hover > div > div{border-color:#fb7299;border-style:solid;border-width:0 2px;width:100%;height:3px;top:6px;left:-2px;position:relative;background:#fb7299}\n                            .bilibili-progress-segmentation > div{box-sizing:border-box;border-style:solid;border-color:#fb7299;border-left-width:2px;position:absolute;width:100%;height:6px;top:12px}\n                            .bilibili-progress-detail-chapter{top:-96px;position:absolute;width:100%;font-size:17px;font-weight:bold;color:#fff;text-shadow:0 0 5px #000}\n                            .bilibili-progress-segmentation:last-child > div{border-right-width:2px}\n                            .bilibili-player-filter-chapter:hover{color:#00a1d6}\n                            .bilibili-player-chapterList{position:relative;height:100%;width:100%;overflow:auto}\n                            .bilibili-player-chapterList::-webkit-scrollbar{width:6px}\n                            .bilibili-player-chapterList::-webkit-scrollbar-track{border-radius:4px;background-color:#fff}\n                            .bilibili-player-chapterList::-webkit-scrollbar-thumb{border-radius:4px;background-color:#fff}\n                            .bilibili-player-chapterList:hover::-webkit-scrollbar-track{background-color:#edf2f9}\n                            .bilibili-player-chapterList:hover::-webkit-scrollbar-thumb{background-color:#a2a2a2}\n                            .bilibili-player-chapter-info{width:100%;height:72px;margin-top:5px;white-space:normal;font-size:14px;position:relative;cursor:pointer}\n                            .bilibili-player-chapter-info > img{position:absolute;left:15px;top:4px;border-radius:2px}\n                            .bilibili-player-chapter-info > p{padding-top:5px;margin:0 5px 5px 138px;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;height:43px}\n                            .bilibili-player-chapter-info:hover > p{color:#00a1d6}\n                            .bilibili-player-chapter-info > span{color:#99a2aa}\n                            .bilibili-player-chapter-info.active{background-color:#f3f3f3}`);\n            }\n            let sliderTracker = document.querySelector(\".bilibili-player-video-progress .bpui-slider-tracker\"); // 播放进度区域,6px\n            let sliderBar = document.getElementsByClassName(\"bilibili-player-video-progress-bar\")[0];\n            let handleWidth = document.getElementsByClassName(\"bpui-slider-handle\")[0].clientWidth; // 进度条圆形把手的宽度\n            let trackerWrp = document.getElementsByClassName(\"bpui-slider-tracker-wrp\")[0]; // 进度条可控区域,28px\n            let videoDuration = window.player.getDuration(); // 视频总时长\n            // 创建显示在视频预览缩略图上方的看点标题\n            let chptName = document.createElement(\"div\");\n            chptName.className = \"bilibili-progress-detail-chapter\";\n            document.querySelector(\".bilibili-player-video-progress-detail\").appendChild(chptName);\n            // 添加分段进度条\n            let type = view_points[0].type; // type = 1:赛事看点,type = 2:视频分段\n            let segDivs = []; // 存放所有分段Div\n            for (let v of view_points) {\n                let seg = document.createElement(\"div\");\n                if (type == \"1\") {\n                    seg.className = \"bilibili-progress-segmentation-logo\";\n                    let title = document.createElement(\"div\"); // 看点标题\n                    title.innerHTML = \"-> \" + v.content;\n                    title.className = \"bilibili-progress-detail-chapter\";\n                    title.style.cssText = \"width: auto; transform: translateX(-50%); display: none\";\n                    let img = document.createElement(\"img\"); // 看点图标\n                    img.id = \"segmentation-logo\";\n                    img.width = 32;\n                    img.height = 36;\n                    img.src = v.logoUrl;\n                    img.addEventListener(\"mousemove\", e => e.stopPropagation());\n                    img.addEventListener(\"mouseenter\", () => {\n                        title.style.display = \"\";\n                        img.style.zIndex = \"1000\";\n                    });\n                    img.addEventListener(\"mouseleave\", () => {\n                        title.style.display = \"none\";\n                        img.style.zIndex = \"\";\n                    });\n                    img.addEventListener(\"click\", () => window.player.seek(v.from));\n                    seg.appendChild(title);\n                    seg.appendChild(img);\n                }\n                else if (type == \"2\") {\n                    seg.className = \"bilibili-progress-segmentation\";\n                    let duration = view_points[view_points.length - 1].to;\n                    let ratio = videoDuration / duration / duration;\n                    seg.style.width = (v.to - v.from) * ratio * 100 + \"%\";\n                    seg.style.left = v.from * ratio * 100 + \"%\";\n                    seg.innerHTML = \"<div><div></div></div>\";\n                    seg.onmouseenter = () => chptName.innerHTML = v.content;\n                }\n                segDivs.push(seg);\n                sliderTracker.appendChild(seg);\n            }\n            if (type == \"1\") {\n                function update() {\n                    for (let i = 0; i < segDivs.length; i++) {\n                        // 进度条上的鼠标坐标与视频时间点的互算公式,从bilibiliPlayer.js复制过来\n                        // 使视频看点标记与点击进度条后实际跳转的时间点准确对应\n                        segDivs[i].style.left = view_points[i].to / videoDuration * (trackerWrp.clientWidth - handleWidth) + handleWidth / 2 + \"px\";\n                    }\n                }\n                setTimeout(() => update(), 500); // 等待进度条完全加载\n                chptName.style.top = \"-140px\";\n                // 鼠标与看点图标的交互、将图标上移避免阻挡视频缩略图\n                trackerWrp.addEventListener(\"mousemove\", e => {\n                    let closestPoint = 1e6;\n                    // 鼠标位置->视频时间点\n                    let box = sliderBar.getBoundingClientRect();\n                    let pos = (e.pageX - (box.left + window.scrollX - document.body.clientLeft) - handleWidth / 2) / (trackerWrp.clientWidth - handleWidth) * videoDuration;\n                    0 > pos && (pos = 0);\n                    pos > videoDuration && (pos = videoDuration);\n                    let thumbnailArea = 80 / (trackerWrp.clientWidth - handleWidth) * videoDuration; // 图标上移的鼠标坐标范围(80px)\n                    let hitArea = trackerWrp.clientWidth > 400 ? thumbnailArea / 10 : thumbnailArea / 20; // 显示标题的鼠标坐标范围\n                    for (let i = 0; i < view_points.length; i++) {\n                        segDivs[i].style.zIndex = \"\";\n                        if (view_points[i].to >= pos - thumbnailArea && view_points[i].to <= pos + thumbnailArea) {\n                            segDivs[i].className = \"bilibili-progress-segmentation-logo active\";\n                            if (view_points[i].to >= pos - hitArea && view_points[i].to <= pos + hitArea && Math.abs(view_points[i].to - pos) < closestPoint) {\n                                chptName.innerHTML = view_points[i].content;\n                                closestPoint = Math.abs(view_points[i].to - pos);\n                                segDivs[i].style.zIndex = \"1000\";\n                            }\n                        }\n                        else {\n                            segDivs[i].className = \"bilibili-progress-segmentation-logo\";\n                        }\n                    }\n                    if (closestPoint == 1e6)\n                        chptName.innerHTML = \"\";\n                });\n                window.player.addEventListener(\"video_player_resize\", () => update());\n                trackerWrp.addEventListener(\"mouseleave\", () => {\n                    for (let i = 0; i < view_points.length; i++) {\n                        segDivs[i].className = \"bilibili-progress-segmentation-logo\";\n                    }\n                });\n            }\n            // 添加“视频看点”面板\n            let wrapList = document.querySelector(\"div.bilibili-player-wraplist\"); // 获取播放器右侧面板的容器div\n            let panels = wrapList.children;\n            let chptInfo = null; // 数组,存放每一看点的UI卡片\n            let chptPanel = document.createElement(\"div\"); // “视频看点”面板\n            chptPanel.style.display = \"none\";\n            chptPanel.className = \"bilibili-player-filter-wrap bilibili-player-chapterList\";\n            wrapList.appendChild(chptPanel);\n            let chptBtn = document.createElement(\"div\"); // “视频看点”按钮\n            chptBtn.className = \"bilibili-player-filter-btn bilibili-player-filter-chapter bpui-component bpui-button bpui-button-type-small button\";\n            chptBtn.innerHTML = '<span class=\"bpui-button-text\"><span>视频看点</span></span>';\n            document.querySelector(\"div.bilibili-player-filter\").appendChild(chptBtn);\n            // 用当前播放进度刷新面板\n            function refreshState() {\n                if (!chptInfo)\n                    return;\n                let progress = window.player.getCurrentTime();\n                for (let i = 0, v; i < view_points.length; i++) {\n                    v = view_points[i];\n                    if (progress < v.to) {\n                        let active = document.querySelector(\".bilibili-player-chapter-info.active\");\n                        active && active.classList.remove(\"active\");\n                        chptInfo[i].classList.add(\"active\");\n                        break;\n                    }\n                }\n            }\n            let timeFormat = (t) => t < 10 ? \"0\" + t : t;\n            chptBtn.onclick = () => {\n                let activePanel = document.querySelector(\"div.bilibili-player-filter-btn.active\");\n                if (activePanel == chptBtn)\n                    return;\n                // 切换按钮的激活状态\n                activePanel.classList.remove(\"active\");\n                chptBtn.classList.add(\"active\");\n                for (let i = 0; i < panels.length; i++) {\n                    const element = panels[i];\n                    if (element.style.display == \"block\") {\n                        element.style.display = \"none\";\n                        break;\n                    }\n                }\n                // 创建各个看点对应的UI卡片\n                if (!chptInfo) {\n                    chptInfo = [];\n                    for (let i = 0, v; i < view_points.length; i++) {\n                        v = view_points[i];\n                        let dura = v.to - v.from;\n                        let div = document.createElement(\"div\");\n                        div.className = \"bilibili-player-chapter-info\";\n                        div.innerHTML = `<img width=\"112\" height=\"63\" src=\"${v.imgUrl}\"/>\n                                        <p class=\"chapter-name\">${v.content}</p>\n                                        <span style=\"margin-left: 138px\">${timeFormat(Math.floor(v.from / 60))}:${timeFormat(v.from % 60)}</span>\n                                        <span style=\"margin-right: 5px; float: right;\">${dura >= 60 ? `${Math.floor(dura / 60)}分` : \"\"}${dura > 0 ? `${dura % 60}秒` : \"\"}</span>`;\n                        div.onclick = (jumpto => () => {\n                            window.player.seek(jumpto);\n                            let active = document.querySelector(\".bilibili-player-chapter-info.active\");\n                            active && active.classList.remove(\"active\");\n                            div.classList.add(\"active\");\n                        })(v.from);\n                        chptInfo[i] = div;\n                        chptPanel.appendChild(div);\n                    }\n                }\n                ;\n                chptPanel.style.display = \"block\";\n                // 将当前的播放进度对应的UI卡片显示为灰色底色\n                refreshState();\n            };\n            window.player.addEventListener(\"video_media_seeked\", refreshState);\n            chptPanel.onmouseenter = refreshState;\n            class timer {\n                static start() { if (!timer.handle)\n                    timer.handle = setInterval(refreshState, 3000); }\n                static stop() { if (timer.handle) {\n                    clearInterval(timer.handle);\n                    timer.handle = null;\n                } }\n            }\n            window.player.addEventListener(\"video_media_playing\", timer.start);\n            window.player.addEventListener(\"video_media_pause\", timer.stop);\n            if (window.player.getState() == \"PLAYING\")\n                timer.start();\n        }\n    }\n    SegProgress.cssInited = false;\n    API.segProgress = (data) => {\n        try {\n            new SegProgress(data);\n        }\n        catch (e) {\n            toast.error(\"segProgress.js\", e);\n        }\n    };\n})();\n\n//# sourceURL=API://@bilibili/dist/required/segProgress.js";
    modules["unloginPopover.js"] = "/**\n * 移除未登录弹窗\n */\n(function () {\n    try {\n        API.runWhile(() => document.querySelector(\".lt-row\"), () => document.querySelector(\".lt-row\").remove());\n        API.runWhile(() => document.querySelector(\".unlogin-popover\"), () => document.querySelector(\".unlogin-popover\").remove());\n    }\n    catch (e) {\n        debug.error(\"unloginPopover.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/required/unloginPopover.js";
    modules["unread.js"] = "/**\n * 本模块负责处理远古顶栏的动态残留问题\n */\n(function () {\n    try {\n        API.jsonphook([\"api.bilibili.com/x/web-feed/feed/unread\"], function (xhr) {\n            xhr.url = xhr.url.replace(\"feed/unread\", \"article/unread\");\n        });\n    }\n    catch (e) {\n        debug.error(\"unread.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/required/unread.js";
    modules["user-select.js"] = "/**\n * 本模块负责截除页面复制限制及右键锁\n * 本模块代码参考自{@see Absolute Enable Right Click & Copy {@link https://chrome.google.com/webstore/detail/jdocbkpgdakpekjlhemmfcncgdjeiika}}\n */\n(function () {\n    try {\n        API.addCss(`* {\n            -webkit-user-select: text !important;\n            -moz-user-select: text !important;\n            -ms-user-select: text !important;\n            user-select: text !important;\n        }`);\n        [].forEach.call(['contextmenu', 'copy', 'cut', 'paste', 'mouseup', 'mousedown', 'keyup', 'keydown', 'drag', 'dragstart', 'select', 'selectstart'], function (event) {\n            document.addEventListener(event, function (e) {\n                e.stopPropagation();\n            }, true);\n        });\n    }\n    catch (e) {\n        debug.error(\"user-select.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/required/user-select.js";
    modules["videoLimit.js"] = "/**\n * 本模块负责解除区域、APP等播放限制\n */\n(function () {\n    try {\n        class HookTimeOut {\n            constructor() {\n                this.hook = setTimeout;\n                window.setTimeout = (...args) => {\n                    if (args[1] && args[1] == 1500 && args[0] && args[0].toString() == \"function(){f.cz()}\") {\n                        toast.warning(\"禁用播放器强制初始化!\", ...args);\n                        return Number.MIN_VALUE;\n                    }\n                    return this.hook.call(window, ...args);\n                };\n            }\n            relese() {\n                window.setTimeout = this.hook;\n            }\n        }\n        API.xhrhook(['season/user/status?'], function (args) {\n            args[1] = args[1].replace('bangumi.bilibili.com/view/web_api/season/user/status', 'api.bilibili.com/pgc/view/web/season/user/status');\n            this.addEventListener('readystatechange', () => {\n                if (this.readyState === 4) {\n                    try {\n                        let response = API.jsonCheck(this.responseText);\n                        if (response) {\n                            if (response.result.area_limit) {\n                                response.result.area_limit = 0;\n                                response.ban_area_show = 1;\n                                API.limit = true;\n                            }\n                            if (response.result.progress)\n                                response.result.watch_progress = response.result.progress;\n                            if (response.result.vip_info)\n                                response.result.vipInfo = response.result.vip_info;\n                            Object.defineProperty(this, 'response', { writable: true });\n                            Object.defineProperty(this, 'responseText', { writable: true });\n                            this.response = this.responseText = JSON.stringify(response);\n                        }\n                    }\n                    catch (e) {\n                        debug.error(\"videoLimit.js\", e);\n                    }\n                }\n            });\n        });\n        API.xhrhook([\"/playurl?\"], function (args) {\n            var _a, _b;\n            // APP限制\n            !API.limit && API.pgc && ((_b = (_a = API.__INITIAL_STATE__) === null || _a === void 0 ? void 0 : _a.rightsInfo) === null || _b === void 0 ? void 0 : _b.watch_platform) && (this.send = async () => appLimit.call(this, args));\n            // 区域限制\n            API.limit && (this.send = async () => areaLimit.call(this, args));\n        });\n        async function appLimit(args) {\n            const hookTimeout = new HookTimeOut();\n            const progress = setInterval(() => { this.dispatchEvent(new ProgressEvent(\"progress\")); }, 50);\n            const accesskey = GM.getValue(\"access_key\", \"\") || undefined;\n            let response;\n            let obj = API.urlObj(args[1]);\n            obj = { ...obj, ...{ access_key: accesskey, fnval: null, fnver: null, platform: \"android_i\" } };\n            this.dispatchEvent(new ProgressEvent(\"loadstart\"));\n            Object.defineProperty(this, \"response\", { writable: true });\n            Object.defineProperty(this, \"responseText\", { writable: true });\n            Object.defineProperty(this, \"responseURL\", { writable: true });\n            Object.defineProperty(this, \"readyState\", { writable: true });\n            Object.defineProperty(this, \"status\", { writable: true });\n            this.status = 200;\n            this.readyState = 2;\n            this.dispatchEvent(new ProgressEvent(\"readystatechange\"));\n            try {\n                toast.info(\"尝试解除APP限制... 使用移动端flv接口\");\n                response = API.jsonCheck(await xhr.GM({\n                    url: API.urlsign(\"https://api.bilibili.com/pgc/player/api/playurl\", obj, 1)\n                }));\n                response = { \"code\": 0, \"message\": \"success\", \"result\": response };\n                API.__playinfo__ = response;\n                toast.success(`解除APP限制!aid=${API.aid}, cid=${API.cid}`);\n            }\n            catch (e) {\n                toast.error(\"videoLimit.js\", e);\n                response = { \"code\": -404, \"message\": e, \"data\": null };\n            }\n            clearInterval(progress);\n            this.responseURL = args[1];\n            this.response = this.responseText = JSON.stringify(response);\n            this.readyState = 4;\n            this.dispatchEvent(new ProgressEvent(\"readystatechange\"));\n            this.dispatchEvent(new ProgressEvent(\"load\"));\n            this.dispatchEvent(new ProgressEvent(\"loadend\"));\n            hookTimeout.relese();\n        }\n        async function areaLimit(args) {\n            if (API.globalLimit)\n                return globalLimit.call(this, args);\n            const hookTimeout = new HookTimeOut();\n            const progress = setInterval(() => { this.dispatchEvent(new ProgressEvent(\"progress\")); }, 50);\n            const accesskey = GM.getValue(\"access_key\", \"\") || undefined;\n            let response;\n            let obj = API.urlObj(args[1]);\n            obj = { ...obj, ...{ access_key: accesskey, module: \"bangumi\" } };\n            obj.fnval && (obj.fnval = 16);\n            this.dispatchEvent(new ProgressEvent(\"loadstart\"));\n            Object.defineProperty(this, \"response\", { writable: true });\n            Object.defineProperty(this, \"responseText\", { writable: true });\n            Object.defineProperty(this, \"responseURL\", { writable: true });\n            Object.defineProperty(this, \"readyState\", { writable: true });\n            Object.defineProperty(this, \"status\", { writable: true });\n            this.status = 200;\n            this.readyState = 2;\n            this.dispatchEvent(new ProgressEvent(\"readystatechange\"));\n            try {\n                toast.info(\"尝试解除区域限制... 访问代理服务器\");\n                response = API.jsonCheck(await xhr.GM({\n                    url: API.objUrl(\"https://www.biliplus.com/BPplayurl.php\", obj)\n                }));\n                response = await new API.RebuildPlayerurl().appPlayurl(response);\n                response = { \"code\": 0, \"message\": \"success\", \"result\": response };\n                API.__playinfo__ = response;\n                toast.success(`解除区域限制!aid=${API.aid}, cid=${API.cid}`);\n            }\n            catch (e) {\n                toast.error(\"videoLimit.js\", e);\n                response = { \"code\": -404, \"message\": e, \"data\": null };\n            }\n            clearInterval(progress);\n            this.responseURL = args[1];\n            this.response = this.responseText = JSON.stringify(response);\n            this.readyState = 4;\n            this.dispatchEvent(new ProgressEvent(\"readystatechange\"));\n            this.dispatchEvent(new ProgressEvent(\"load\"));\n            this.dispatchEvent(new ProgressEvent(\"loadend\"));\n            hookTimeout.relese();\n        }\n        async function globalLimit(args) {\n            const hookTimeout = new HookTimeOut();\n            const progress = setInterval(() => { this.dispatchEvent(new ProgressEvent(\"progress\")); }, 50);\n            const server = config.limitServer || \"https://api.global.bilibili.com\";\n            let response;\n            let obj = API.urlObj(args[1]);\n            this.dispatchEvent(new ProgressEvent(\"loadstart\"));\n            Object.defineProperty(this, \"response\", { writable: true });\n            Object.defineProperty(this, \"responseText\", { writable: true });\n            Object.defineProperty(this, \"responseURL\", { writable: true });\n            Object.defineProperty(this, \"readyState\", { writable: true });\n            Object.defineProperty(this, \"status\", { writable: true });\n            this.status = 200;\n            this.readyState = 2;\n            this.dispatchEvent(new ProgressEvent(\"readystatechange\"));\n            try {\n                toast.info(\"尝试解除泰区限制... 访问代理服务器\");\n                response = API.jsonCheck(await xhr.GM({\n                    url: API.objUrl(`${server}/intl/gateway/v2/ogv/playurl`, { aid: obj.avid || API.aid, ep_id: obj.ep_id, download: \"1\" })\n                }));\n                response = await new API.RebuildPlayerurl().ogvPlayurl(response);\n                response = { \"code\": 0, \"message\": \"success\", \"result\": response };\n                API.__playinfo__ = response;\n                toast.success(`解除泰区限制!aid=${API.aid}, cid=${API.cid}`);\n            }\n            catch (e) {\n                toast.error(\"videoLimit.js\", e);\n                response = { \"code\": -404, \"message\": e, \"data\": null };\n            }\n            clearInterval(progress);\n            this.responseURL = args[1];\n            this.response = this.responseText = JSON.stringify(response);\n            this.readyState = 4;\n            this.dispatchEvent(new ProgressEvent(\"readystatechange\"));\n            this.dispatchEvent(new ProgressEvent(\"load\"));\n            this.dispatchEvent(new ProgressEvent(\"loadend\"));\n            hookTimeout.relese();\n        }\n    }\n    catch (e) {\n        toast.error(\"videoLimit.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/required/videoLimit.js";
    modules["danmaku.js"] = "/**\n * 本模块提供各种弹幕相关工具,负责获取、转化等弹幕处理功能\n * `本模块按需加载,使用相关函数前请务必先载入本模块`\n * 新版弹幕相关功能调用了开源项目`protobufjs`,非常感谢,相关信息如下\n * @see protobufjs {@link https://github.com/protobufjs/protobuf.js}\n * @license BSD 3-Clause\n */\n(function () {\n    try {\n        class Danmaku {\n            constructor() {\n                new Function(GM.getResourceText(\"protobuf.min.js\"))(); // protobufjs引擎\n                Danmaku.root = window.protobuf.Root.fromJSON(API.getModule(\"protobuf.json\"));\n                Danmaku.protoSeg = Danmaku.root.lookupType('bilibili.DmSegMobileReply');\n                Danmaku.protoView = Danmaku.root.lookupType('bilibili.DmWebViewReply');\n            }\n            /**\n             * 生成xml形式的弹幕\n             * @param danmaku protoSeg.decode(new Uint8Array(this.response)).elems\n             * @returns 委托对象,表示生成的xml形式的弹幕字符串\n             */\n            toXml(danmaku) {\n                let DM = Reflect.has(danmaku[0], \"idStr\") ? this.danmakuFormat(danmaku) : danmaku;\n                this.sortDmById(DM, \"dmid\");\n                let xml = DM.reduce((s, d) => {\n                    s += `<d p=\"${d.stime},${d.mode},${d.size},${d.color},${d.date},${d.class},${d.uid},${d.dmid}\">${d.text.replace(/[<\">'&]/g, (a) => { return { '<': '&lt;', '\"': '&quot;', '>': '&gt;', \"'\": '&#39;', '&': '&amp;' }[a]; }).replace(/(\\n|\\r\\n)/g, \"/n\")}</d>\\r\\n`;\n                    return s;\n                }, '<?xml version=\"1.0\" encoding=\"UTF-8\"?><i><chatserver>chat.bilibili.com</chatserver><chatid>' + API.cid + '</chatid><mission>0</mission><maxlimit>99999</maxlimit><state>0</state><real_name>0</real_name><source>e-r</source>\\r\\n');\n                xml += \"</i>\";\n                /**\n                 * remove-invalid-xml-characters.js\n                 * @link https://gist.github.com/john-doherty/b9195065884cdbfd2017a4756e6409cc\n                 * @license MIT\n                 * @see https://en.wikipedia.org/wiki/Valid_characters_in_XML\n                 */\n                var regex = /((?:[\\0-\\x08\\x0B\\f\\x0E-\\x1F\\uFFFD\\uFFFE\\uFFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]))/g;\n                return xml.replace(regex, '');\n            }\n            /**\n             * 将弹幕数组按弹幕id升序排序\n             * @param danmaku 要排序的弹幕数组\n             * @param key 弹幕id的属性名,应为dmid或idStr\n             */\n            sortDmById(danmaku, key) {\n                let egx = /^\\d+$/;\n                for (let i = 0, d; i < danmaku.length; i++) {\n                    d = danmaku[i];\n                    // 判断输入是否纯数字\n                    if (!egx.test(d[key]))\n                        throw \"请输入数字字符串\";\n                    // 强制转化输入为字符串\n                    if (typeof d[key] !== \"string\")\n                        d[key] = String(d[key]);\n                    // 去除数字开头占位的0\n                    d[key] = d[key].replace(/^0+/, \"\");\n                }\n                danmaku.sort((a, b) => this.bigInt(a[key], b[key]) ? 1 : -1);\n            }\n            /**\n             * 比较大小,仅用于弹幕排序\n             * @param num1 数字字符串 1\n             * @param num2 数字字符串 2\n             * @returns 前者大于后者返回真,否则返回假,相等也返回假\n             */\n            bigInt(num1, num2) {\n                // 数位不同,前者大为真,否则为假\n                if (num1.length > num2.length)\n                    return true;\n                else if (num1.length < num2.length)\n                    return false;\n                else {\n                    // 数位相同,逐位比较\n                    for (let i = 0; i < num1.length; i++) {\n                        // 任意一位前者大为真\n                        if (num1[i] > num2[i])\n                            return true;\n                        // 任意一位前者小为假\n                        if (num1[i] < num2[i])\n                            return false;\n                        // 仅当位相等时继续比较下一位\n                    }\n                    // 包括相等情况返回假\n                    return false;\n                }\n            }\n            /**\n             * 获取 proto 弹幕\n             * @param aid 弹幕所对应视频的 aid,当前视频请留空\n             * @param cid 弹幕所对应视频的 cid,当前视频请留空\n             * @param bas 是否只获取BAS/代码弹幕,默认请留空\n             * @returns 弹幕数组:Promise\n             */\n            async getSegDanmaku(aid = API.aid, cid = API.cid, bas = false) {\n                try {\n                    // 判断参数是否有效\n                    aid = aid || API.aid;\n                    cid = cid || API.cid;\n                    if (!aid || !cid)\n                        throw [\"弹幕参数错误!\", \"aid:\" + aid, \"cid:\" + cid];\n                    // 首先获取弹幕分片总数\n                    let config = await xhr({\n                        url: API.objUrl(\"https://api.bilibili.com/x/v2/dm/web/view\", {\n                            type: String(1),\n                            oid: String(cid),\n                            pid: String(aid)\n                        }),\n                        responseType: \"arraybuffer\",\n                        credentials: true\n                    });\n                    config = Danmaku.protoView.decode(new Uint8Array(config));\n                    // dmSge.total代表的分片总数,有时错误地为100\n                    // 故需要按照 视频时长/分片时长(一般是360秒) 把分片总数计算出来\n                    let pageSize = config.dmSge.pageSize ? config.dmSge.pageSize / 1000 : 360;\n                    let total = (window.player && window.player.getDuration && (window.player.getDuration() / pageSize + 1)) || config.dmSge.total;\n                    let allrequset = [], allDanmaku = [];\n                    // 其他视频的分片总数已经不能从当前window下获取\n                    if (API.aid && (aid != API.aid))\n                        total = config.dmSge.total;\n                    if (!bas) {\n                        // 特殊情况下只需要BAS/高级弹幕时 bas为真\n                        for (let index = 1; index <= total; index++) {\n                            allrequset.push(xhr({\n                                url: API.objUrl(\"https://api.bilibili.com/x/v2/dm/web/seg.so\", {\n                                    type: String(1),\n                                    oid: String(cid),\n                                    pid: String(aid),\n                                    segment_index: String(index)\n                                }),\n                                responseType: \"arraybuffer\",\n                                credentials: true\n                            }));\n                        }\n                    }\n                    // BAS弹幕\n                    if (config.specialDms.length > 0) {\n                        for (let index = 0; index < config.specialDms.length; index++) {\n                            // 下发的是http链接,但会被chrome的安全措施拦掉,于是替换成https\n                            allrequset.push(xhr({\n                                url: config.specialDms[index].replace(\"http\", \"https\"),\n                                responseType: \"arraybuffer\",\n                                credentials: false\n                            }));\n                        }\n                    }\n                    // 互动弹幕\n                    let upHighlightDm = []; // 带有蓝色“UP主”特殊标记的弹幕\n                    if (config.commandDms.length > 0) {\n                        for (let i = 0; i < config.commandDms.length; i++) {\n                            let cdm = config.commandDms[i];\n                            if (cdm.command == \"#UP#\") {\n                                cdm.styleClass = \"danmaku-up-icon\";\n                                cdm.color = 16777215;\n                                cdm.pool = 0;\n                                cdm.fontsize = 25;\n                                cdm.ctime = new Date(cdm.mtime).getTime() / 1000;\n                                cdm.mode = 1;\n                                cdm.midHash = API.crc32 && API.crc32(cdm.mid);\n                                upHighlightDm.push(cdm);\n                                config.commandDms.splice(i, 1);\n                            }\n                        }\n                        if (API.loadCommandDm && API.config.commandDm)\n                            API.loadCommandDm(config.commandDms, aid, cid);\n                    }\n                    // 解码弹幕\n                    (await Promise.all(allrequset)).forEach(d => {\n                        if (d)\n                            allDanmaku = allDanmaku.concat(Danmaku.protoSeg.decode(new Uint8Array(d)).elems);\n                    });\n                    return allDanmaku.concat(upHighlightDm);\n                }\n                catch (e) {\n                    toast.error(\"danmaku.js\", e);\n                }\n            }\n            /**\n             * 获取历史弹幕\n             * @param date 历史弹幕日期,yyyy-mm-dd格式:如 2009-06-24\n             * @param cid 弹幕所在视频的 cid,不填则取当前视频的cid\n             * @returns 解析好的弹幕数组\n             */\n            async getHistoryDanmaku(date, cid = API.cid) {\n                if (!date || !API.uid)\n                    return;\n                cid = cid || API.cid;\n                let dm = await xhr({\n                    url: API.objUrl(\"https://api.bilibili.com/x/v2/dm/web/history/seg.so\", {\n                        type: String(1),\n                        oid: String(cid),\n                        date: date\n                    }),\n                    responseType: \"arraybuffer\",\n                    credentials: true\n                });\n                return this.segDmDecode(dm);\n            }\n            /**\n             * 载入本地弹幕\n             * @param xml 读取本地弹幕文件得到的字符串\n             * @param append 默认为false,即不保留已加载的弹幕。为true时,则将追加到现有弹幕上\n             */\n            loadLocalDm(xml, append) {\n                var _a, _b;\n                let doc = new DOMParser().parseFromString(xml, \"application/xml\");\n                let dm = doc.querySelectorAll(\"d\");\n                if (dm.length == 0) {\n                    toast.warning(\"从弹幕文件中没有获取到任何弹幕!\");\n                    return;\n                }\n                let danmaku = [];\n                let attr, v, mode;\n                for (let i = 0; i < dm.length; i++) {\n                    v = dm[i];\n                    attr = v.getAttribute('p').split(\",\");\n                    mode = parseInt(attr[1]);\n                    danmaku[i] = {\n                        class: parseInt(attr[5]),\n                        color: parseInt(attr[3]),\n                        date: parseInt(attr[4]),\n                        dmid: attr[7],\n                        mode: mode,\n                        size: parseInt(attr[2]),\n                        stime: parseFloat(attr[0]),\n                        text: ((mode != 8 && mode != 9) ? v.textContent.replace(/(\\/n|\\\\n|\\n|\\r\\n)/g, '\\n') : v.textContent),\n                        uid: attr[6]\n                    };\n                }\n                this.specialEffects(danmaku);\n                this.sortDmById(danmaku, \"dmid\");\n                /**\n                 * bilibiliPlayer.js 21394行已经添加如下代码,用于设置弹幕池\n                 * @param  {Array} dm 弹幕数组\n                 * @param  {Boolean} append 默认为false,即不保留已加载的弹幕。为true时,则将追加到现有弹幕上\n                 */\n                // setDanmaku = (dm) => {......}\n                if (!((_a = window.player) === null || _a === void 0 ? void 0 : _a.setDanmaku))\n                    return toast.error(\"刷新弹幕列表失败:播放器内部调用丢失!\");\n                (_b = window.player) === null || _b === void 0 ? void 0 : _b.setDanmaku(danmaku, append);\n            }\n            /**\n             * 把有换行符的弹幕的zindex设为它的出现时间(progress),并且打上“字幕弹幕”标记\n             * @param dm 弹幕数组\n             */\n            specialEffects(dm) {\n                let textData;\n                for (let i = 0; i < dm.length; i++) {\n                    textData = dm[i];\n                    if (textData.text.includes('\\n')) {\n                        textData.class = 1;\n                        textData.zIndex = textData.stime * 1000;\n                        if (!(textData.text.includes(\"█\") || textData.text.includes(\"▂\")))\n                            textData.zIndex = textData.zIndex + 1;\n                    }\n                }\n            }\n            segDmDecode(response) {\n                return Danmaku.protoSeg.decode(new Uint8Array(response)).elems;\n            }\n            /**\n             * 将新版弹幕数组转化为旧版弹幕数组\n             * @param dm 新版弹幕数组\n             * @param aid 视频aid,默认取当前视频aid\n             * @returns 旧版弹幕数组\n             */\n            danmakuFormat(dm, aid) {\n                aid = aid || API.aid;\n                let danmaku = dm.map(function (v) {\n                    let result = {\n                        class: v.pool,\n                        color: v.color,\n                        date: v.ctime,\n                        dmid: v.idStr,\n                        mode: v.mode,\n                        size: v.fontsize,\n                        stime: v.progress / 1000,\n                        text: (v.mode != 8 && v.mode != 9) ? v.content.replace(/(\\/n|\\\\n|\\n|\\r\\n)/g, '\\n') : v.content,\n                        uid: v.midHash\n                    };\n                    // 添加图片弹幕信息\n                    if (v.action && v.action.startsWith(\"picture:\"))\n                        result.picture = \"//\" + v.action.split(\":\")[1];\n                    // 利用bilibiliPlayer.js的这行代码,可以添加指定的css类到弹幕上\n                    // b.AH && (e.className = e.className + \" \" + b.AH);\n                    if (v.styleClass !== undefined)\n                        result.AH = v.styleClass;\n                    return result;\n                });\n                //对av400000(2012年11月)之前视频中含有\"/n\"的弹幕的进行专门处理\n                if (aid && aid < 400000) {\n                    this.specialEffects(danmaku);\n                }\n                this.sortDmById(danmaku, \"dmid\");\n                return danmaku;\n            }\n            /**\n             * 载入在线弹幕\n             * @param url 其他弹幕所在视URL\n             */\n            async onlineDanmaku(url) {\n                try {\n                    let obj = await API.urlInputCheck(url);\n                    if (obj.aid && obj.cid) {\n                        API.getSegDanmaku(obj.aid, obj.cid).then(d => {\n                            var _a;\n                            d = API.danmakuFormat(d, obj.aid);\n                            (_a = window.player) === null || _a === void 0 ? void 0 : _a.setDanmaku(d, config.concatDanmaku);\n                            API.danmaku = d;\n                        });\n                    }\n                }\n                catch (e) {\n                    debug.error(\"onlineDanmaku.js\", e);\n                }\n            }\n        }\n        const DM = new Danmaku();\n        API.getSegDanmaku = (aid = API.aid, cid = API.cid, bas = false) => DM.getSegDanmaku(aid, cid, bas);\n        API.specialEffects = (dm) => DM.specialEffects(dm);\n        API.sortDmById = (danmaku, key) => DM.sortDmById(danmaku, key);\n        API.toXml = (danmaku) => DM.toXml(danmaku);\n        API.getHistoryDanmaku = (date, cid) => DM.getHistoryDanmaku(date, cid);\n        API.loadLocalDm = (xml, append) => DM.loadLocalDm(xml, append);\n        API.segDmDecode = (response) => DM.segDmDecode(response);\n        API.danmakuFormat = (dm, aid) => DM.danmakuFormat(dm, aid);\n        API.onlineDanmaku = (url) => DM.onlineDanmaku(url);\n    }\n    catch (e) {\n        toast.error(\"danmaku.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/units/danmaku.js";
    modules["debug.js"] = "(function () {\n    class Debug {\n        static log(...data) { console.log(`%c[${API.timeFormat()}]`, \"color: blue;\", ...data); }\n        static info(...data) { console.info(`%c[${API.timeFormat()}]`, \"color: green;\", ...data); }\n        static debug(...data) { console.debug(`[${API.timeFormat()}]`, ...data); }\n        static warn(...data) { console.warn(`[${API.timeFormat()}]`, ...data); }\n        static error(...data) { console.error(`[${API.timeFormat()}]`, ...data); }\n    }\n    // @ts-ignore\n    API.debug = (...data) => Debug.log(...data);\n    Reflect.ownKeys(Debug).forEach(d => typeof Debug[d] == \"function\" && Reflect.set(Reflect.get(API, \"debug\"), d, Debug[d]));\n})();\n\n//# sourceURL=API://@bilibili/dist/units/debug.js";
    modules["element.js"] = "/**\n * 本模块负责提供一些内置的可复用的HTMLEliment组件\n */\n(function () {\n    try {\n        class ClickRemove {\n            /**\n             * 对一个节点添加监听,点击该节点之外的地方移除该节点\n             * @param ele 目标节点\n             */\n            constructor(ele) {\n                setTimeout(() => {\n                    function remove() {\n                        ele.remove();\n                        document.removeEventListener(\"click\", remove);\n                    }\n                    document.addEventListener(\"click\", remove);\n                    ele.addEventListener(\"click\", e => e.stopPropagation());\n                }, 100);\n            }\n        }\n        class Element {\n            /**\n             * 弹出一个空白浮动窗口,点击该窗口外的节点该窗口会自动关闭\n             * 浮动窗口上的内容请通过返回的节点进行后续添加\n             * @param style 添加style样式,直接写进element,具有最高优先级\n             * @param hold 禁用自动关闭,转而提供一个关闭按钮\n             * @returns 浮动窗口实际可操作节点,可以往上面添加需要显示在浮动窗口上的内容\n             */\n            static popupbox(style = {}, hold) {\n                const box = API.addElement(\"div\", { class: \"ui-popup-box\" });\n                const real = box.attachShadow({ mode: \"closed\" });\n                const div = API.addElement(\"div\", { class: \"box\" }, real);\n                const popup = API.addElement(\"div\", { class: \"contain\" }, div);\n                API.addCss(API.getModule(\"ui-popup-box.css\"), undefined, real);\n                Object.keys(style).forEach(d => popup.style[d] = style[d]);\n                hold ? this.close(div, box) : new ClickRemove(box);\n                return popup;\n            }\n            /**\n             * 添加关闭按钮\n             * @param ele 按钮所在节点\n             * @param box 点击按钮关闭的节点,不存在则取ele\n             */\n            static close(ele, box) {\n                const svg = this.svg('<svg viewBox=\"0 0 100 100\"><path d=\"M2 2 L98 98 M 98 2 L2 98Z\" stroke-width=\"10px\" stroke=\"#212121\" stroke-linecap=\"round\"></path></svg>');\n                svg.setAttribute(\"style\", \"position: absolute;transform: scale(0.8);right: 10px;top: 10px;\");\n                svg.onclick = () => box ? box.remove() : ele.remove();\n                ele.appendChild(svg);\n            }\n            /**\n             * 封装hr标签,一条水平直线,一般用于隔断节点\n             * @returns 封装好的节点\n             */\n            static hr() {\n                const hr = document.createElement(\"div\");\n                const real = hr.attachShadow({ mode: \"closed\" });\n                API.addElement(\"div\", { class: \"hr\" }, real);\n                API.addCss(API.getModule(\"hr.css\"), undefined, real);\n                return hr;\n            }\n            /**\n             * 封装svg图标标签\n             * @param svg svg节点字符串\n             * @returns 封装好的节点\n             */\n            static svg(svg) {\n                const root = document.createElement(\"div\");\n                const real = root.attachShadow({ mode: \"closed\" });\n                API.addElement(\"div\", { class: \"icon\" }, real, svg);\n                API.addCss(API.getModule(\"icon.css\"), undefined, real);\n                return root;\n            }\n            /**\n             * 封装好的滑块快关标签\n             * @param callback 一个用于接收滑块开关响应的回调函数,必须,否则外部无法获取或响应开关状态\n             * @param value 开关初始状态,非必须,默认为false\n             * @returns 封装好的节点\n             */\n            static switch(callback, value) {\n                const root = document.createElement(\"div\");\n                const real = root.attachShadow({ mode: \"closed\" });\n                const div = API.addElement(\"div\", {\n                    class: \"switch\"\n                }, real, `<span class=\"bar\"></span>\n            <span class=\"knob\"><i class=\"circle\"></i></span>`);\n                API.addCss(API.getModule(\"switch.css\"), undefined, real);\n                value = value ? true : false;\n                value && (div.children[0].setAttribute(\"checked\", \"checked\"),\n                    div.children[1].setAttribute(\"checked\", \"checked\"),\n                    div.children[1].children[0].setAttribute(\"checked\", \"checked\"));\n                div.onclick = () => {\n                    value = !value;\n                    value ? (div.children[0].setAttribute(\"checked\", \"checked\"),\n                        div.children[1].setAttribute(\"checked\", \"checked\"),\n                        div.children[1].children[0].setAttribute(\"checked\", \"checked\")) : (div.children[0].removeAttribute(\"checked\"),\n                        div.children[1].removeAttribute(\"checked\"),\n                        div.children[1].children[0].removeAttribute(\"checked\"));\n                    callback.call(div, value);\n                };\n                return root;\n            }\n            /**\n             * 获取并整合内置Css模块\n             * @param svg Css模块名序列\n             * @returns 整合好的Css模块\n             */\n            static getCss(...svg) {\n                return svg.reduce((s, d) => {\n                    s += `\\r\\n${API.getModule(d)}`;\n                    return s;\n                }, \"\");\n            }\n            /**\n             * 封装好的下拉列表标签(单选)\n             * @param list 下拉表值组\n             * @param callback 一个用于接收下拉选择响应的回调函数,必须,否则外部无法获取或响应选择状态\n             * @param value 初始选定值\n             * @returns 封装好的节点\n             */\n            static select(list, callback, value) {\n                const root = document.createElement(\"div\");\n                const real = root.attachShadow({ mode: \"closed\" });\n                const div = API.addElement(\"div\", { class: \"select\" }, real);\n                const select = list.reduce((s, d) => {\n                    API.addElement(\"option\", {}, s, d);\n                    return s;\n                }, API.addElement(\"select\", {}, div));\n                API.addCss(this.getCss(\"select.css\"), undefined, real);\n                select.value = value || select.options[0].text;\n                select.onchange = () => callback.call(div, select.value);\n                return root;\n            }\n            /**\n             * 封装好的按钮标签\n             * @param callback 响应按钮点击的回调函数,必须,否则无法响应按钮点击事件\n             * @param text 按钮上的文字,默认为“确定”\n             * @param disabled 点击按钮后的CD,单位:/s,默认为1,取0表示一直禁用\n             * @returns 封装好的节点\n             */\n            static button(callback, text, disabled = 1) {\n                const root = document.createElement(\"div\");\n                const real = root.attachShadow({ mode: \"closed\" });\n                const div = API.addElement(\"div\", { class: \"button\" }, real, text || \"确定\");\n                API.addCss(this.getCss(\"button.css\"), undefined, real);\n                div.onclick = () => {\n                    div.setAttribute(\"disabled\", \"disabled\");\n                    callback.call(div);\n                    disabled && setTimeout(() => div.removeAttribute(\"disabled\"), disabled * 1000);\n                };\n                return root;\n            }\n            /**\n             * 封装好的输入框,响应回车事件\n             * @param callback 响应输入确认的回调函数,必须,否则无法响应输入\n             * @param text 输入框内默认数据,非必须\n             * @param attribute input标签的标准属性,用于指定输入框类型等\n             * @param pattern 检测输入的正则表达式,将过滤非法输入并弹出toast警告\n             * @param button 输入框右侧带上按钮,响应按钮点击事件而非回车事件\n             * @param disabled 点击按钮后的CD,单位:/s,默认为1,取0表示一直禁用\n             * @returns 封装好的节点\n             */\n            static input(callback, text, attribute, pattern, button, disabled) {\n                const root = document.createElement(\"div\");\n                const real = root.attachShadow({ mode: \"closed\" });\n                const div = API.addElement(\"div\", { class: \"input\" }, real);\n                const input = API.addElement(\"input\", {}, div);\n                API.addCss(this.getCss(\"input.css\"), undefined, real);\n                attribute && Object.entries(attribute).forEach(d => { input.setAttribute(d[0], d[1]); });\n                text && (input.value = text);\n                button ? div.appendChild(this.button(function () {\n                    if (pattern && !pattern.test(input.value))\n                        return toast.warning(`值 ${input.value} 不符合要求!`, `正则表达式:${pattern.toString()}`);\n                    callback.call(input, input.value);\n                }, button, disabled)) : input.onchange = () => {\n                    if (pattern && !pattern.test(input.value))\n                        return toast.warning(`值 ${input.value} 不符合要求!`, `正则表达式:${pattern.toString()}`);\n                    callback.call(input, input.value);\n                };\n                return root;\n            }\n            /**\n             * 封装好的文件选择按钮,特化版的输入框\n             * @param callback 响应文件选择结果的回调函数,必须,否则无法响应文件选择\n             * @param multiple 是否允许多选,默认为false\n             * @param text 选择按钮上的文字,默认为“选择”\n             * @param accept 指定文件类型拓展名组,不指定默认取所有类型文件\n             * @returns 封装好的节点\n             */\n            static file(callback, multiple, text = \"选择\", accept) {\n                const root = document.createElement(\"div\");\n                const real = root.attachShadow({ mode: \"closed\" });\n                const input = API.addElement(\"input\", { type: \"file\", style: \"width: 0;position: absolute;\" }, real);\n                accept && (input.accept = accept.join(\",\"));\n                multiple && (input.multiple = true);\n                real.appendChild(this.button(() => input.click(), text, 0));\n                input.onchange = () => input.files && callback.call(input, input.files);\n                return root;\n            }\n            /**\n             * 封装好的复选框(多选)\n             * @param list 复选框的值组\n             * @param callback 响应选择操作的回调函数,必须,否则无法响应文件选择\n             * @param value list中的默认选中数据组,非必须\n             * @returns 封装好的节点\n             */\n            static checkbox(list, callback, value = []) {\n                const root = document.createElement(\"div\");\n                const real = root.attachShadow({ mode: \"closed\" });\n                const div = API.addElement(\"div\", { class: \"box\" }, real);\n                API.addCss(this.getCss(\"checkbox.css\"), undefined, real);\n                const checkboxs = list.reduce((s, d) => {\n                    s.push(API.addElement(\"div\", { class: \"checkbox\" }, div, `<div class=\"checklabel\">\n                        <div class=\"disc-border\"></div>\n                        <div class=\"disc\"></div>\n                    </div>\n                    <div class=\"checkvalue\">${d}</div>`));\n                    return s;\n                }, []);\n                const checks = list.reduce((s, d) => {\n                    s.push(value.includes(d));\n                    return s;\n                }, []);\n                checkboxs.forEach((d, i) => {\n                    checks[i] && (d.children[0].children[0].setAttribute(\"checked\", \"checked\"),\n                        d.children[0].children[1].setAttribute(\"checked\", \"checked\"));\n                    d.onclick = () => {\n                        checks[i] = !checks[i];\n                        checks[i] ? (d.children[0].children[0].setAttribute(\"checked\", \"checked\"),\n                            d.children[0].children[1].setAttribute(\"checked\", \"checked\")) : (d.children[0].children[0].removeAttribute(\"checked\"),\n                            d.children[0].children[1].removeAttribute(\"checked\"));\n                        callback.call(div, checks.reduce((s, d, i) => { d && s.push(list[i]); return s; }, []));\n                    };\n                });\n                return root;\n            }\n            /**\n             * 封装好的进度条,自适应父节点width\n             * @param detail 进度条配置,双向绑定:**修改其中的值会及时体现在该进度条上**\n             * @returns 封装好的节点\n             */\n            static progress(detail) {\n                let { min, max, value, color, nocolor, display } = detail;\n                const root = document.createElement(\"div\");\n                const real = root.attachShadow({ mode: \"closed\" });\n                API.addCss(API.getCss(\"progress.css\"), undefined, real);\n                const progress = API.addElement(\"div\", { class: \"progress\" }, real);\n                const progressContainer = API.addElement(\"div\", { class: \"progressContainer\", title: \"0%\" }, progress);\n                const secondaryProgress = API.addElement(\"div\", { class: \"secondaryProgress\", style: \"transform: scaleX(0);\" }, progressContainer);\n                const primaryProgress = API.addElement(\"div\", { class: \"primaryProgress\", style: \"transform: scaleX(0);\" }, progressContainer);\n                const progressTag = API.addElement(\"div\", { class: \"progressTag\", style: \"display: none;\" }, progress, `<div>${min}</div><div>${max}</div>`);\n                Object.defineProperties(detail, {\n                    \"color\": { get: () => primaryProgress.style.backgroundColor, set: (v) => primaryProgress.style.backgroundColor = v },\n                    \"display\": { get: () => progressTag.style.display, set: (v) => progressTag.style.display = v ? \"\" : \"none\" },\n                    \"max\": {\n                        get: () => max, set: (v) => {\n                            if (v < value || v <= min)\n                                return;\n                            progressTag.children[1].innerText = max = v;\n                            detail.value = value;\n                        }\n                    },\n                    \"min\": {\n                        get: () => min, set: (v) => {\n                            if (v > value || v >= max)\n                                return;\n                            progressTag.children[0].innerText = min = v;\n                            detail.value = value;\n                        }\n                    },\n                    \"nocolor\": { get: () => secondaryProgress.style.backgroundColor, set: (v) => secondaryProgress.style.backgroundColor = v },\n                    \"value\": {\n                        get: () => value, set: (v) => {\n                            if (v > max || v < min)\n                                return;\n                            const per = Number(((v - min) / (max - min)).toFixed(3).slice(0, -1));\n                            primaryProgress.style.transform = `scaleX(${per})`;\n                            progressContainer.title = (per * 100) + \"%\";\n                        }\n                    }\n                });\n                min >= max && (min = 0);\n                (value > max || value < min) && (value = 0);\n                detail.min = min, detail.max = max, detail.value = value, detail.color = color, detail.nocolor = nocolor, detail.display = display;\n                return root;\n            }\n        }\n        API.element = {\n            popupbox: (style, hold) => Element.popupbox(style, hold),\n            hr: () => Element.hr(),\n            svg: (svg) => Element.svg(svg),\n            switch: (callback, value) => Element.switch(callback, value),\n            select: (list, callback, value) => Element.select(list, callback, value),\n            button: (callback, text, disabled) => Element.button(callback, text, disabled),\n            input: (callback, text, attribute, pattern, button, disabled) => Element.input(callback, text, attribute, pattern, button, disabled),\n            file: (callback, multiple, text, accept) => Element.file(callback, multiple, text, accept),\n            checkbox: (list, callback, value) => Element.checkbox(list, callback, value),\n            clickRemove: (ele) => new ClickRemove(ele),\n            progress: (detail) => Element.progress(detail)\n        };\n        API.getCss = (...svg) => Element.getCss(...svg);\n    }\n    catch (e) {\n        toast.error(\"element.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/units/element.js";
    modules["extend.js"] = "/**\n * 本模块负责拓展一些小工具,这些工具不便写在主模块中\n */\n(function () {\n    try {\n        function getCookies() {\n            return document.cookie.split('; ').reduce((s, d) => {\n                let key = d.split('=')[0];\n                let val = d.split('=')[1];\n                s[key] = val;\n                return s;\n            }, {});\n        }\n        API.getCookies = () => getCookies();\n        async function loginExit(referer) {\n            if (!API.uid)\n                return toast.warning(\"本就未登录,无法退出登录!\");\n            toast.warning(\"正在退出登录...\");\n            let data = API.jsonCheck(await xhr({\n                url: \"https://passport.bilibili.com/login/exit/v2\",\n                data: `biliCSRF=${API.getCookies().bili_jct}&gourl=${encodeURIComponent(location.href)}`,\n                method: \"POST\",\n                credentials: true\n            }));\n            if (data.status) {\n                toast.success(\"退出登录!\");\n                if (referer)\n                    return location.replace(referer);\n                setTimeout(() => location.reload(), 1000);\n            }\n        }\n        API.loginExit = (referer) => loginExit(referer);\n        function jsonCheck(data) {\n            let result = typeof data === \"string\" ? JSON.parse(data) : data;\n            if (\"code\" in result && result.code !== 0) {\n                let msg = result.msg || result.message || \"\";\n                throw [result.code, msg];\n            }\n            return result;\n        }\n        API.jsonCheck = (data) => jsonCheck(data);\n        function restorePlayerSetting() {\n            var _a;\n            let bilibili_player_settings = localStorage.getItem(\"bilibili_player_settings\");\n            let settings_copy = GM.getValue(\"bilibili_player_settings\", {});\n            if (bilibili_player_settings) {\n                let settings = JSON.parse(bilibili_player_settings);\n                if (((_a = settings === null || settings === void 0 ? void 0 : settings.video_status) === null || _a === void 0 ? void 0 : _a.autopart) !== \"\")\n                    GM.setValue(\"bilibili_player_settings\", settings);\n                else if (settings_copy)\n                    localStorage.setItem(\"bilibili_player_settings\", JSON.stringify(settings_copy));\n            }\n            else if (settings_copy) {\n                localStorage.setItem(\"bilibili_player_settings\", JSON.stringify(settings_copy));\n            }\n        }\n        API.restorePlayerSetting = () => restorePlayerSetting();\n        function biliQuickLogin() {\n            window.biliQuickLogin ? window.biliQuickLogin() : window.$ ? window.$.getScript(\"//static.hdslb.com/account/bili_quick_login.js\", () => window.biliQuickLogin()) : false;\n        }\n        API.biliQuickLogin = () => biliQuickLogin();\n        function getTotalTop(node) {\n            var sum = 0;\n            do {\n                sum += node.offsetTop;\n                node = node.offsetParent;\n            } while (node);\n            return sum;\n        }\n        API.getTotalTop = (node) => getTotalTop(node);\n        async function saveAs(content, fileName, contentType = \"text/plain\") {\n            const a = document.createElement(\"a\");\n            const file = new Blob([content], { type: contentType });\n            a.href = URL.createObjectURL(file);\n            a.download = fileName;\n            a.click();\n        }\n        function getUrlValue(name) {\n            const reg = new RegExp(\"(^|&)\" + name + \"=([^&]*)(&|$)\", \"i\");\n            const r = window.location.search.substr(1).match(reg);\n            if (r != null)\n                return decodeURIComponent(r[2]);\n            return null;\n        }\n        API.getUrlValue = (name) => getUrlValue(name);\n        API.saveAs = (content, fileName, contentType) => saveAs(content, fileName, contentType);\n        function readAs(file, type = \"string\", encoding) {\n            return new Promise((resolve, reject) => {\n                const reader = new FileReader();\n                switch (type) {\n                    case \"ArrayBuffer\":\n                        reader.readAsArrayBuffer(file);\n                        break;\n                    case \"DataURL\":\n                        reader.readAsDataURL(file);\n                        break;\n                    case \"string\":\n                        reader.readAsText(file, encoding || 'utf-8');\n                        break;\n                }\n                reader.onload = () => resolve(reader.result);\n                reader.onerror = e => reject(e);\n            });\n        }\n        API.readAs = (file, type, encoding) => readAs(file, type, encoding);\n        const aids = {};\n        async function getAidInfo(aid) {\n            if (!aids[aid]) {\n                const data = await xhr({\n                    url: `https://api.bilibili.com/x/web-interface/view/detail?aid=${aid}`,\n                    responseType: \"json\",\n                    credentials: true\n                });\n                aids[aid] = data.data;\n            }\n            return aids[aid];\n        }\n        API.getAidInfo = (aid) => getAidInfo(aid);\n        function strSize(str) {\n            let size = 0;\n            for (let i = 0; i < str.length; i++) {\n                const code = str.charCodeAt(i);\n                if (code <= 0x007f)\n                    size++;\n                else if (code <= 0x07ff)\n                    size += 2;\n                else if (code <= 0xffff)\n                    size += 3;\n                else\n                    size += 4;\n            }\n            return size;\n        }\n        API.strSize = (str) => strSize(str);\n        function intervalFormat(time) {\n            time >= 1e11 && (time = Math.floor(time / 1e3));\n            const now = Math.floor((new Date).getTime() / 1e3);\n            let t = new Date;\n            if (t.setHours(0), t.setMinutes(0), t.setSeconds(0), (t = Math.floor(t.getTime() / 1e3)) < time && 0 <= now - time) {\n                if (now - time <= 50) {\n                    var r = 10 * Math.floor((now - time) % 60 / 10);\n                    return (10 < time ? r : 10) + \"秒前\";\n                }\n                return now - time < 3600 ? Math.floor((now - time) / 60) + \"分钟前\" : Math.floor((now - time) / 3600) + \"小时前\";\n            }\n            return API.timeFormat(time * 1e3, true);\n        }\n        API.intervalFormat = (time) => intervalFormat(time);\n        async function addCss(txt, id, parrent) {\n            if (!parrent && !document.head) {\n                await new Promise(r => API.runWhile(() => document.body, r));\n            }\n            parrent = parrent || document.head;\n            const style = document.createElement(\"style\");\n            style.setAttribute(\"type\", \"text/css\");\n            id && !parrent.querySelector(`#${id}`) && style.setAttribute(\"id\", id);\n            style.appendChild(document.createTextNode(txt));\n            parrent.appendChild(style);\n        }\n        API.addCss = (txt, id, parrent) => addCss(txt, id, parrent);\n        function addElement(tag, attribute, parrent, innerHTML, top, replaced) {\n            let element = document.createElement(tag);\n            attribute && (Object.entries(attribute).forEach(d => element.setAttribute(d[0], d[1])));\n            parrent = parrent || document.body;\n            innerHTML && (element.innerHTML = innerHTML);\n            replaced ? replaced.replaceWith(element) : top ? parrent.insertBefore(element, parrent.firstChild) : parrent.appendChild(element);\n            return element;\n        }\n        API.addElement = (tag, attribute, parrent, innerHTML, top, replaced) => addElement(tag, attribute, parrent, innerHTML, top, replaced);\n        function runWhile(check, callback, delay = 100, stop = 180) {\n            let timer = setInterval(() => {\n                if (check()) {\n                    clearInterval(timer);\n                    callback();\n                }\n            }, delay);\n            stop && setTimeout(() => clearInterval(timer), stop * 1000);\n        }\n        API.runWhile = (check, callback, delay = 100, stop = 180) => runWhile(check, callback, delay, stop);\n        function bofqiMessage(msg, time = 3, callback, replace = true) {\n            let node = document.querySelector(\".bilibili-player-video-toast-bottom\");\n            if (!node) {\n                if (msg) {\n                    if (Array.isArray(msg))\n                        return debug.log(...msg);\n                    return debug.log(msg);\n                }\n                return;\n            }\n            if (!msg)\n                node.childNodes.forEach(d => d.remove());\n            const table = document.querySelector(\".bilibili-player-video-toast-item.bilibili-player-video-toast-pay\") || document.createElement(\"div\");\n            table.setAttribute(\"class\", \"bilibili-player-video-toast-item bilibili-player-video-toast-pay\");\n            const ele = document.createElement(\"div\");\n            ele.setAttribute(\"class\", \"bilibili-player-video-toast-item-text\");\n            table.appendChild(ele);\n            msg = Array.isArray(msg) ? msg : [msg];\n            if (!msg[0])\n                return;\n            replace && node.childNodes.forEach(d => d.remove());\n            ele.innerHTML = msg.reduce((s, d, i) => {\n                if (d) {\n                    switch (i) {\n                        case 0:\n                            s += `<span class=\"video-float-hint-text\">${d}</span>`;\n                            break;\n                        case 1:\n                            s += `<span class=\"video-float-hint-btn hint-red\">${d}</span>`;\n                            break;\n                        case 2:\n                            s += `<span class=\"video-float-hint-btn\">${d}</span>`;\n                            break;\n                    }\n                }\n                return s;\n            }, '');\n            node.appendChild(table);\n            callback && (ele.style.cursor = \"pointer\") && (ele.onclick = () => callback());\n            (time !== 0) && setTimeout(() => {\n                ele.remove();\n                !table.children[0] && table.remove();\n            }, time * 1000);\n        }\n        API.bofqiMessage = (msg, time, callback, replace) => bofqiMessage(msg, time, callback, replace);\n        async function alertMessage(text, title = API.Name) {\n            return new Promise((r) => {\n                const root = API.addElement(\"div\");\n                const div = root.attachShadow({ mode: \"closed\" });\n                const table = API.addElement(\"div\", { class: \"table\" }, div, `\n            <div class=\"title\">${title}</div>\n            <div class=\"text\">${text}</div>\n            <div class=\"act\">\n                <div class=\"button\">确认</div>\n                <div class=\"button\">取消</div>\n                </div>\n            `);\n                API.addCss(API.getCss(\"alert.css\", \"button.css\"), '', div);\n                table.querySelectorAll(\".button\").forEach((d, i) => {\n                    i ? (d.onclick = () => { root.remove(), r(false); }) : (d.onclick = () => (root.remove(), r(true)));\n                });\n            });\n        }\n        API.alertMessage = (text, title) => alertMessage(text, title);\n    }\n    catch (e) {\n        toast.error(\"extend.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/units/extend.js";
    modules["format.js"] = "(function () {\n    class Format {\n        /**\n         * 格式化时间\n         * @param time 时间戳\n         * @param type 是否包含年月日\n         * @returns 时:分:秒 | 年-月-日 时:分:秒\n         */\n        static timeFormat(time = new Date().getTime(), type) {\n            let date = new Date(time), Y = date.getFullYear() + '-', M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-', D = (date.getDate() < 10 ? '0' + (date.getDate()) : date.getDate()) + ' ', h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':', m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) + ':', s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());\n            return type ? Y + M + D + h + m + s : h + m + s;\n        }\n        /**\n         * 格式化字节\n         * @param size 字节/B\n         * @returns n B | K | M | G\n         */\n        static sizeFormat(size = 0) {\n            let unit = [\"B\", \"K\", \"M\", \"G\"], i = unit.length - 1, dex = 1024 ** i, vor = 1000 ** i;\n            while (dex > 1) {\n                if (size >= vor) {\n                    size = Number((size / dex).toFixed(2));\n                    break;\n                }\n                dex = dex / 1024;\n                vor = vor / 1000;\n                i--;\n            }\n            return size ? size + unit[i] : \"N/A\";\n        }\n        /**\n         * 格式化进位\n         * @param num 实数\n         * @returns n 万 | 亿\n         */\n        static unitFormat(num = 0) {\n            num = 1 * num || 0;\n            let unit = [\"\", \"万\", \"亿\"], i = unit.length - 1, dex = 10000 ** i;\n            while (dex > 1) {\n                if (num >= dex) {\n                    num = Number((num / dex).toFixed(1));\n                    break;\n                }\n                dex = dex / 10000;\n                i--;\n            }\n            return num + unit[i];\n        }\n        /**\n         * 冒泡排序\n         * @param arr 待排序数组\n         * @returns 排序结果\n         */\n        static bubbleSort(arr) {\n            let temp;\n            for (let i = 0; i < arr.length - 1; i++) {\n                let bool = true;\n                for (let j = 0; j < arr.length - 1 - i; j++) {\n                    if (arr[j] > arr[j + 1]) {\n                        temp = arr[j];\n                        arr[j] = arr[j + 1];\n                        arr[j + 1] = temp;\n                        bool = false;\n                    }\n                }\n                if (bool)\n                    break;\n            }\n            return arr;\n        }\n        /**\n         * 随机截取指定大小子数组\n         * @param arr 母数组\n         * @param num 子数组大小\n         * @returns 子数组\n         */\n        static randomArray(arr, num) {\n            let out = [];\n            num = num || 1;\n            num = num < arr.length ? num : arr.length;\n            while (out.length < num) {\n                var temp = (Math.random() * arr.length) >> 0;\n                out.push(arr.splice(temp, 1)[0]);\n            }\n            return out;\n        }\n        /**\n         * search参数对象拼合回URL\n         * @param url URL主体,可含search参数\n         * @param obj search参数对象\n         * @returns 拼合的URL\n         */\n        static objUrl(url, obj) {\n            let data = this.urlObj(url);\n            obj = typeof obj === \"object\" ? obj : {};\n            data = Object.assign(data, obj);\n            let arr = [], i = 0;\n            for (let key in data) {\n                if (data[key] !== undefined && data[key] !== null) {\n                    arr[i] = key + \"=\" + data[key];\n                    i++;\n                }\n            }\n            if (url)\n                url = url + \"?\" + arr.join(\"&\");\n            else\n                url = arr.join(\"&\");\n            if (url.charAt(url.length - 1) == \"?\")\n                url = url.split(\"?\")[0];\n            return url;\n        }\n        /**\n         * 提取URL search参数对象\n         * @param url 原URL\n         * @returns search参数对象\n         */\n        static urlObj(url = \"\") {\n            let arr = url.split('?')[1] ? url.split('?')[1].split('&') : [];\n            return arr.reduce((o, d) => {\n                if (d.includes(\"#\"))\n                    d = d.split(\"#\")[0];\n                if (d)\n                    o[d.split('=')[0]] = d.split('=')[1] || \"\";\n                return o;\n            }, {});\n        }\n    }\n    Reflect.ownKeys(Format).forEach(d => typeof Format[d] == \"function\" && Reflect.set(API, d, Format[d]));\n})();\n\n//# sourceURL=API://@bilibili/dist/units/format.js";
    modules["manage.js"] = "/**\n * 本模块负责维护脚本数据存储\n */\n(function () {\n    class Config {\n        constructor() {\n            this.box = API.element.popupbox({ maxWidth: \"360px\", maxHeight: \"300px\" });\n            API.addElement(\"div\", { style: 'text-align: center;font-size: 16px;font-weight: bold;margin-bottom: 10px;' }, this.box, `<span>设置数据<span>`);\n            API.addElement(\"div\", { style: 'margin-bottom: 10px;' }, this.box, `<div>设置数据包含您个人对于设置的自定义调整,不包括内置的模块、安装的第三方模块以及各种功能缓存的数据。您可以选择恢复默认数据、导出为本地文件或者从本地文件中恢复。</div>`);\n            this.box.appendChild(API.element.hr());\n            const body = API.addElement(\"div\", { style: \"display: flex;align-items: center;justify-content: space-around;\" }, this.box);\n            body.appendChild(API.element.button(() => { this.restore(); }, \"默认\", 0));\n            body.appendChild(API.element.button(() => { this.output(); }, \"导出\", 0));\n            body.appendChild(API.element.file((v) => { this.input(v); }, false, \"导入\", [\".json\"]));\n        }\n        restore() {\n            GM.deleteValue(\"config\");\n            toast.warning(\"已恢复默认数据,请及时刷新页面避免数据紊乱!\");\n            API.alertMessage(`已恢复默认数据,请及时<strong>刷新</strong>页面避免数据紊乱!`, \"恢复默认设置\").then(d => { d && location.reload(); });\n        }\n        output() {\n            API.saveAs(JSON.stringify(config, undefined, \"\\t\"), `config ${API.timeFormat(undefined, true)}.json`, \"application/json\");\n        }\n        input(v) {\n            v && v[0] && API.readAs(v[0]).then(d => {\n                const data = JSON.parse(d);\n                Object.keys(data).forEach(d => Reflect.has(config, d) && Reflect.set(config, d, data[d]));\n                toast.success(\"已导入本地设置数据,请刷新页面生效!\");\n            });\n        }\n    }\n    new Config();\n})();\n\n//# sourceURL=API://@bilibili/dist/units/manage.js";
    modules["nodeObserver.js"] = "/**\n * 本模块负责DOM节点变动监听\n * **监听节点变动开销极大,如非必要请改用其他方法并且用后立即销毁!**\n */\n(function () {\n    const nodelist = [];\n    /**\n     * 注册节点添加监听\n     * **监听节点变动开销极大,如非必要请改用其他方法并且用后立即销毁!**\n     * @param callback 添加节点后执行的回调函数\n     * @returns 注册编号,用于使用`removeObserver`销毁监听\n     */\n    function observerAddedNodes(callback) {\n        try {\n            if (typeof callback === \"function\")\n                nodelist.push(callback);\n            return nodelist.length - 1;\n        }\n        catch (e) {\n            toast.error(\"nodeObserver.js\", e);\n        }\n    }\n    API.observerAddedNodes = (callback) => observerAddedNodes(callback);\n    /**\n     * 销毁`observerAddedNodes`监听\n     * @param id 注册`observerAddedNodes`监听是返回的编号\n     */\n    function removeObserver(id) {\n        nodelist.splice(id, 1);\n    }\n    API.removeObserver = (id) => removeObserver(id);\n    (new MutationObserver(d => d.forEach(d => {\n        d.addedNodes[0] && nodelist.forEach(async (f) => f(d.addedNodes[0]));\n    }))).observe(document, { childList: true, subtree: true });\n})();\n\n//# sourceURL=API://@bilibili/dist/units/nodeObserver.js";
    modules["rewrite.js"] = "/**\n * 重写引导,重写操作是非常底层的操作,必须在正常引导之前。\n */\n(function () {\n    try {\n        API.uid = Number(API.getCookies().DedeUserID);\n        API.path = location.href.split(\"/\");\n        if (API.uid) {\n            // 代理旧版退出登录页面\n            if (location.href.includes(\"bilibili.com/login?act=exit\"))\n                API.loginExit(document.referrer);\n            // 修复动态时间线\n            let offset = API.getCookies()[\"bp_video_offset_\" + API.uid];\n            offset && (document.cookie = \"bp_t_offset_\" + API.uid + \"=\" + offset + \"; domain=bilibili.com; expires=Aug, 18 Dec 2038 18:00:00 GMT; BLOD.path=/\");\n        }\n        API.importModule(\"parameterTrim.js\", { Before: true }, true); // 网址清理,重写前处理\n        /**\n         * 分离页面进入重写判定\n         */\n        if (config.av && /\\/video\\/[AaBb][Vv]/.test(location.href))\n            API.importModule(\"av.js\");\n        if (config.bangumi && /\\/bangumi\\/play\\/(ss|ep)/.test(location.href))\n            API.importModule(\"bangumi.js\");\n        if (config.watchlater && /\\/watchlater\\//.test(location.href))\n            API.importModule(\"watchlater.js\");\n        if (config.player && /player\\./.test(location.href))\n            API.importModule(\"player.js\");\n        if (/space\\.bilibili\\.com/.test(location.href))\n            API.importModule(\"space.js\");\n        if (config.index && API.path[2] == 'www.bilibili.com' && (!API.path[3] || (API.path[3].startsWith('\\?') || API.path[3].startsWith('\\#') || API.path[3].startsWith('index.'))))\n            API.importModule(\"index.js\");\n        if (config.ranking && /\\/v\\/popular\\//.test(location.href))\n            API.importModule(\"ranking.js\");\n        if (/live\\.bilibili\\.com/.test(location.href))\n            API.importModule(\"live.js\");\n        if (/\\/medialist\\/play\\//.test(location.href))\n            API.importModule(\"mediaList.js\");\n        if (config.anime && /\\/anime\\/?(\\?.+)?$/.test(location.href))\n            API.importModule(\"anime.js\");\n        if (API.path[2] == \"message.bilibili.com\")\n            API.addCss(API.getModule(\"message.css\"));\n        if (window.self == window.top && API.path[2] == 'www.bilibili.com')\n            document.domain = \"bilibili.com\";\n        if (location.href.includes(\"message.bilibili.com/pages/nav/index_new_sync\"))\n            API.addCss(API.getModule(\"imroot.css\"));\n        if (location.href.includes(\"www.bilibili.com/account/history\"))\n            API.importModule(\"history.js\");\n        if (/dmid/.test(location.href) && /dm_progress/.test(location.href))\n            API.importModule(\"loadByDmid.js\");\n        if (config.read && /\\/read\\/[Cc][Vv]/.test(location.href))\n            API.importModule(\"read.js\");\n        if (config.player && /festival\\/2021bnj/.test(location.href))\n            API.importModule(\"bnj2021.js\");\n        API.scriptIntercept([\"bilibiliPlayer.min.js\"], \"https://cdn.jsdelivr.net/gh/MotooriKashin/Bilibili-Old/dist/bilibiliPlayer.min.js\"); // 播放器脚本拦截\n        /**\n         * 若页面不需要重写,直接进入正常引导\n         */\n        (!API.path.name || config.rewriteMethod == \"同步\") && API.importModule(\"vector.js\");\n    }\n    catch (e) {\n        toast.error(\"rewrite.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/units/rewrite.js";
    modules["setting.js"] = "/**\n * 本模块负责集中注册相关设置项\n */\n(function () {\n    try {\n        // 注册设置菜单\n        API.registerMenu({ key: \"common\", name: \"通用\", svg: '<svg viewBox=\"0 0 24 24\"><g><path d=\"M22.7 19l-9.1-9.1c.9-2.3.4-5-1.5-6.9-2-2-5-2.4-7.4-1.3L9 6 6 9 1.6 4.7C.4 7.1.9 10.1 2.9 12.1c1.9 1.9 4.6 2.4 6.9 1.5l9.1 9.1c.4.4 1 .4 1.4 0l2.3-2.3c.5-.4.5-1.1.1-1.4z\"></path></g></svg>' });\n        API.registerMenu({ key: \"rewrite\", name: \"重写\", svg: `<svg viewBox=\"0 0 24 24\"><g><path d=\"M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z\"></path></g></svg>` });\n        API.registerMenu({ key: \"restore\", name: \"修复\", svg: `<svg viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M5 3.25a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm0 2.122a2.25 2.25 0 10-1.5 0v.878A2.25 2.25 0 005.75 8.5h1.5v2.128a2.251 2.251 0 101.5 0V8.5h1.5a2.25 2.25 0 002.25-2.25v-.878a2.25 2.25 0 10-1.5 0v.878a.75.75 0 01-.75.75h-4.5A.75.75 0 015 6.25v-.878zm3.75 7.378a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm3-8.75a.75.75 0 100-1.5.75.75 0 000 1.5z\"></path></svg>` });\n        API.registerMenu({ key: \"style\", name: \"样式\", svg: `<svg viewBox=\"0 0 24 24\"><g><path d=\"M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01-.23-.26-.38-.61-.38-.99 0-.83.67-1.5 1.5-1.5H16c2.76 0 5-2.24 5-5 0-4.42-4.03-8-9-8zm-5.5 9c-.83 0-1.5-.67-1.5-1.5S5.67 9 6.5 9 8 9.67 8 10.5 7.33 12 6.5 12zm3-4C8.67 8 8 7.33 8 6.5S8.67 5 9.5 5s1.5.67 1.5 1.5S10.33 8 9.5 8zm5 0c-.83 0-1.5-.67-1.5-1.5S13.67 5 14.5 5s1.5.67 1.5 1.5S15.33 8 14.5 8zm3 4c-.83 0-1.5-.67-1.5-1.5S16.67 9 17.5 9s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z\"></path></g></svg>` });\n        API.registerMenu({ key: \"danmaku\", name: \"弹幕\", svg: `<svg viewBox=\"0 0 22 22\"><path d=\"M16.5 8c1.289 0 2.49.375 3.5 1.022V6a2 2 0 00-2-2H4a2 2 0 00-2 2v10a2 2 0 002 2h7.022A6.5 6.5 0 0116.5 8zM7 13H5a1 1 0 010-2h2a1 1 0 010 2zm2-4H5a1 1 0 010-2h4a1 1 0 010 2z\"></path><path d=\"M20.587 13.696l-.787-.131a3.503 3.503 0 00-.593-1.051l.301-.804a.46.46 0 00-.21-.56l-1.005-.581a.52.52 0 00-.656.113l-.499.607a3.53 3.53 0 00-1.276 0l-.499-.607a.52.52 0 00-.656-.113l-1.005.581a.46.46 0 00-.21.56l.301.804c-.254.31-.456.665-.593 1.051l-.787.131a.48.48 0 00-.413.465v1.209a.48.48 0 00.413.465l.811.135c.144.382.353.733.614 1.038l-.292.78a.46.46 0 00.21.56l1.005.581a.52.52 0 00.656-.113l.515-.626a3.549 3.549 0 001.136 0l.515.626a.52.52 0 00.656.113l1.005-.581a.46.46 0 00.21-.56l-.292-.78c.261-.305.47-.656.614-1.038l.811-.135A.48.48 0 0021 15.37v-1.209a.48.48 0 00-.413-.465zM16.5 16.057a1.29 1.29 0 11.002-2.582 1.29 1.29 0 01-.002 2.582z\"></path></svg>` });\n        API.registerMenu({ key: \"player\", name: \"播放\", svg: `<svg viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M1.5 8a6.5 6.5 0 1113 0 6.5 6.5 0 01-13 0zM8 0a8 8 0 100 16A8 8 0 008 0zM6.379 5.227A.25.25 0 006 5.442v5.117a.25.25 0 00.379.214l4.264-2.559a.25.25 0 000-.428L6.379 5.227z\"></path></svg>` });\n        API.registerMenu({ key: \"live\", name: \"直播\", svg: `<svg viewBox=\"0 0 1024 1024\"><path d=\"M392.448 275.911111a92.416 92.416 0 1 1-184.832 0 92.416 92.416 0 0 1 184.832 0\"></path><path d=\"M826.624 464.583111l-63.744 36.864v-48.64a72.206222 72.206222 0 0 0-71.68-71.936H190.72a72.192 72.192 0 0 0-71.936 71.936V748.231111a71.936 71.936 0 0 0 71.936 71.936H691.2a71.936 71.936 0 0 0 71.936-71.936v-23.808l63.488 37.888a51.2 51.2 0 0 0 76.8-44.544V508.871111a51.2 51.2 0 0 0-76.8-44.288M572.928 369.351111c79.459556 0.142222 143.985778-64.156444 144.128-143.616 0.142222-79.459556-64.156444-143.985778-143.616-144.128-79.260444-0.142222-143.701333 63.857778-144.128 143.104-0.426667 79.459556 63.644444 144.213333 143.104 144.64h0.512\"></path><path d=\"M425.216 512.967111l124.16 71.936a25.6 25.6 0 0 1 0 42.496l-124.16 71.68a25.6 25.6 0 0 1-37.12-21.248V534.471111a25.6 25.6 0 0 1 37.12-21.504\"></path></svg>` });\n        API.registerMenu({ key: \"download\", name: \"下载\", svg: `<svg viewBox=\"0 0 24 24\"><g><path d=\"M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z\"></path></g></svg>` });\n        // 注册设置项\n        API.registerSetting({\n            key: \"developer\",\n            sort: \"common\",\n            label: \"开发者模式\",\n            svg: '<svg viewBox=\"0 0 24 24\"><g><path d=\"M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z\"></path></g></svg>',\n            type: \"switch\",\n            value: false,\n            float: '开发者模式将暴露核心变量 <b>API</b> 到页面顶级对象 window,可以借此在控制台调试部分功能。',\n            sub: '暴露 API 到 window',\n            action: (value) => {\n                value ? (!window.API && (window.API = API)) : (window.API && delete window.API);\n            }\n        });\n        config.developer && (window.API = API);\n        API.registerSetting({\n            key: \"rewriteMethod\",\n            sort: \"rewrite\",\n            label: \"重写模式\",\n            sub: \"兼容性选项\",\n            type: \"row\",\n            value: \"同步\",\n            list: [\"同步\", \"异步\"],\n            float: '同步模式能够更有效阻断原生脚本执行,减少原生脚本对于页面的破坏,<strong>缺点是与其他脚本或拓展兼容性不佳</strong>。</br>异步模式尝试提高兼容性,相对应的阻断效果下降,新版页面一闪而过现象加剧且受网络延时影响更大。'\n        });\n        API.registerSetting({\n            key: \"av\",\n            sort: \"rewrite\",\n            label: \"av/BV\",\n            type: \"switch\",\n            value: true,\n            float: '重写以恢复旧版av视频播放页。'\n        });\n        API.registerSetting({\n            key: \"upList\",\n            sort: \"style\",\n            label: \"UP主列表\",\n            sub: \"展示视频合作者\",\n            type: \"switch\",\n            value: false\n        });\n        API.registerSetting({\n            key: \"electric\",\n            sort: \"player\",\n            label: \"跳过充电鸣谢\",\n            sub: \"在视频末尾\",\n            type: \"switch\",\n            value: false\n        });\n        API.registerSetting({\n            key: \"enlike\",\n            sort: \"player\",\n            label: \"添加点赞功能\",\n            sub: \"自制、简陋\",\n            type: \"switch\",\n            value: false,\n            float: \"旧版播放器的时代点赞功能还未存在,本脚本代为设计了个丑丑的点赞功能。\"\n        });\n        API.registerSetting({\n            key: \"medialist\",\n            sort: \"rewrite\",\n            label: \"medialist\",\n            type: \"switch\",\n            value: false,\n            float: \"用旧版av页重构medialist页面。\"\n        });\n        API.registerSetting({\n            type: \"switch\",\n            key: \"index\",\n            label: \"主页\",\n            value: true,\n            sort: \"rewrite\",\n            float: '重写以恢复旧版主页'\n        });\n        API.registerSetting({\n            type: \"switch\",\n            key: \"indexLoc\",\n            label: \"过滤主页广告\",\n            sub: \"banner+recommand\",\n            value: false,\n            sort: \"style\",\n            float: '当然指的是旧版主页。'\n        });\n        API.registerSetting({\n            type: \"switch\",\n            key: \"privateRecommend\",\n            label: \"禁用主页个性化推荐\",\n            sub: \"还是习惯全站统一推荐\",\n            value: false,\n            sort: \"style\",\n            float: '禁用旧版主页banner右边的个性化推荐,恢复全站统一推荐。'\n        });\n        API.registerSetting({\n            key: \"protoDm\",\n            sort: \"danmaku\",\n            label: \"启用新版弹幕\",\n            sub: \"proto弹幕\",\n            type: \"switch\",\n            value: true,\n            float: `添加旧版播放器新版proto弹幕支持。由于旧版xml弹幕已获取不到90分钟后的弹幕,本功能不建议禁用。</br>”`\n        });\n        API.registerSetting({\n            key: \"liveDm\",\n            sort: \"danmaku\",\n            label: \"修复实时弹幕\",\n            sub: \"及时接收别人新发的弹幕\",\n            type: \"switch\",\n            value: true,\n            float: `修复旧版播放器实时弹幕。`\n        });\n        API.registerSetting({\n            key: \"commandDm\",\n            sort: \"danmaku\",\n            label: \"添加互动弹幕\",\n            sub: \"投票弹窗等\",\n            type: \"switch\",\n            value: false,\n            float: `可以使用新版的一些弹窗互动组件。目前可用组件:评分弹窗、投屏弹窗、关联视频跳转按钮、带“UP主”标识弹幕。</br>※ <strong>需要同时开启新版proto弹幕。</strong>`\n        });\n        API.registerSetting({\n            key: \"logReport\",\n            sort: \"common\",\n            label: \"日志拦截\",\n            svg: '<svg viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M1.5 1.75a.75.75 0 00-1.5 0v12.5c0 .414.336.75.75.75h14.5a.75.75 0 000-1.5H1.5V1.75zm14.28 2.53a.75.75 0 00-1.06-1.06L10 7.94 7.53 5.47a.75.75 0 00-1.06 0L3.22 8.72a.75.75 0 001.06 1.06L7 7.06l2.47 2.47a.75.75 0 001.06 0l5.25-5.25z\"></path></svg>',\n            sub: \"拦截B站日志上报\",\n            float: \"网页端日志采集太频繁,稍微动下鼠标都要发送数条日志请求,给network调试带来额外的困扰。\",\n            type: \"switch\",\n            value: false\n        });\n        API.registerSetting({\n            key: \"heartbeat\",\n            sort: \"restore\",\n            label: \"修复视频心跳\",\n            sub: \"出现不记录播放历史症状时的选择\",\n            float: \"尝试修复可能被广告拦截扩展误伤的视频心跳。\",\n            type: \"switch\",\n            value: false\n        });\n        API.registerSetting({\n            key: \"noVideo\",\n            sort: \"player\",\n            label: \"拦截视频载入\",\n            sub: \"用于临时不加载视频进入视频页面\",\n            float: \"拦截播放器载入视频,强行使视频失效。\",\n            type: \"switch\",\n            value: false\n        });\n        API.registerSetting({\n            key: \"bannerGif\",\n            sort: \"style\",\n            label: \"丰富顶栏动图\",\n            sub: '搜索框下gif',\n            float: \"替换顶栏动图接口,避免单调。\",\n            type: \"switch\",\n            value: true\n        });\n        API.registerSetting({\n            key: \"danmakuFirst\",\n            sort: \"style\",\n            label: \"自动切换到弹幕列表\",\n            sub: \"默认是展示推荐视频\",\n            float: \"自动从推荐视频切换到播放弹幕列表。\",\n            type: \"switch\",\n            value: false\n        });\n        API.registerSetting({\n            type: \"sort\",\n            key: \"autoDo\",\n            label: \"自动化操作\",\n            sort: \"player\",\n            sub: \"进入播放页面及切P时\",\n            list: [{\n                    key: \"showBofqi\",\n                    sort: \"style\",\n                    label: \"自动滚动到播放器\",\n                    type: \"switch\",\n                    value: false\n                }, {\n                    key: \"screenWide\",\n                    sort: \"style\",\n                    label: \"自动宽屏\",\n                    type: \"switch\",\n                    value: false\n                }, {\n                    key: \"noDanmaku\",\n                    sort: \"style\",\n                    label: \"自动关弹幕\",\n                    type: \"switch\",\n                    value: false\n                }, {\n                    key: \"autoPlay\",\n                    sort: \"style\",\n                    label: \"自动播放\",\n                    type: \"switch\",\n                    value: false\n                }]\n        });\n        API.registerSetting({\n            key: \"segProgress\",\n            sort: \"player\",\n            label: \"分段进度条\",\n            sub: \"仅限看点视频\",\n            type: \"switch\",\n            value: false\n        });\n        API.registerSetting({\n            key: \"replyList\",\n            sort: \"style\",\n            label: \"恢复评论翻页\",\n            sub: \"可以选择跳转而不必一直下拉\",\n            type: \"switch\",\n            value: true,\n            float: '恢复旧版翻页评论区。</br>重写过的页面除外,那些默认就是翻页评论区。'\n        });\n        API.registerSetting({\n            key: \"section\",\n            sort: \"style\",\n            label: \"统一换回旧版顶栏\",\n            sub: \"针对未重写的页面\",\n            type: \"switch\",\n            value: true,\n            float: '非重写页面顶栏底栏也替换为旧版。'\n        });\n        API.registerSetting({\n            key: \"concatDanmaku\",\n            sort: \"danmaku\",\n            label: \"合并载入弹幕\",\n            sub: \"本地弹幕/在线弹幕\",\n            type: \"switch\",\n            value: false,\n            float: '载入本地弹幕文件或者在线弹幕时是否与播放器当前弹幕合并。'\n        });\n        API.registerSetting({\n            key: \"danmakuHashId\",\n            sort: \"danmaku\",\n            label: \"反查弹幕发送者\",\n            sub: \"结果仅供参考!\",\n            type: \"switch\",\n            value: false,\n            float: '旧版播放器上右键弹幕将显示弹幕发送者。</br>※ 使用哈希逆向算法,存在碰撞可能性,所示信息仅供参考,或者干脆查不出来。'\n        });\n        API.registerSetting({\n            type: \"switch\",\n            key: \"errands\",\n            label: '恢复对于<a href=\"//space.bilibili.com/11783021\" target=\"_blank\">番剧出差</a>和<a href=\"//space.bilibili.com/1988098633\" target=\"_blank\">DM組</a>的访问',\n            sub: '还好没赶尽杀绝',\n            value: true,\n            sort: \"restore\",\n            float: '使用备份数据修复对于番剧出差官方空间的访问。'\n        });\n        API.registerSetting({\n            type: \"switch\",\n            key: \"album\",\n            label: \"还原个人空间相簿链接\",\n            sub: \"相簿比动态页面好看\",\n            value: false,\n            sort: \"restore\",\n            float: '将个人空间的相簿链接从动态重定向回原来的相簿。'\n        });\n        API.registerSetting({\n            type: \"switch\",\n            key: \"jointime\",\n            label: \"显示账号注册时间\",\n            sub: \"历史不该被隐藏\",\n            value: false,\n            sort: \"restore\",\n            float: '在空间显示对应账号的注册时间。'\n        });\n        API.registerSetting({\n            key: \"lostVideo\",\n            sort: \"restore\",\n            label: \"修复失效视频信息\",\n            sub: `有些甚至评论还在!`,\n            type: \"switch\",\n            value: false,\n            float: '使用第三方数据修复收藏、频道等处的失效视频信息。(以红色删除线标记)</br>访问失效视频链接时将尝试重建av页面。</br>※ 依赖第三方数据库且未必有效,<strong>请谨慎考虑是否开启!</strong>'\n        });\n        API.registerSetting({\n            key: \"bangumi\",\n            sort: \"rewrite\",\n            label: \"bangumi\",\n            sub: \"ss/ep\",\n            type: \"switch\",\n            value: true,\n            float: '重写以恢复旧版bangumi播放页。'\n        });\n        API.registerSetting({\n            key: \"limit\",\n            sort: \"player\",\n            label: \"解除区域/平台限制\",\n            sub: \"港澳台?泰版?仅限APP?\",\n            float: \"同类功能脚本可能会冲突,使用专用脚本切莫开启本功能!\",\n            type: \"sort\",\n            list: [\n                {\n                    key: \"videoLimit\",\n                    sort: \"player\",\n                    label: \"解除限制\",\n                    type: \"switch\",\n                    value: false,\n                    sub: \"区域+APP\"\n                }, {\n                    key: \"limitAccesskey\",\n                    sort: \"player\",\n                    label: \"账户授权\",\n                    sub: \"泰区除外\",\n                    type: \"action\",\n                    title: \"管理\",\n                    action: () => { API.showAccesskey(); }\n                }, {\n                    key: \"limitServer\",\n                    sort: \"player\",\n                    label: \"泰区代理\",\n                    type: \"input\",\n                    value: \"https://api.global.bilibili.com\",\n                    float: \"泰区番剧限制需要自备相应的代理服务器(需要https协议头但无需末尾的斜杠!)</br>中文域名请先使用punycode转化一下。</br>本功能由于缺乏调试条件维护不善请多担待!\",\n                    input: { type: \"url\", placeholder: \"URL\" },\n                    pattern: /(\\w+):\\/\\/([^/:]+)(:\\d*)?([^# ]*)/\n                }\n            ]\n        });\n        API.registerSetting({\n            key: \"bangumiEplist\",\n            sort: \"player\",\n            label: \"保留番剧回目列表\",\n            sub: \"牺牲特殊背景图\",\n            type: \"switch\",\n            value: false,\n            float: '部分带特殊背景图片的番剧会隐藏播放器下方的番剧回目列表,二者不可得兼,只能选一。'\n        });\n        API.registerSetting({\n            key: \"episodeData\",\n            sort: \"style\",\n            label: \"显示番剧分集数据\",\n            sub: \"原本是合集数据\",\n            type: \"switch\",\n            value: false,\n            float: '有分集数据时将bangumi播放、弹幕数替换为当集数据。原合集数据将显示在鼠标焦点信息上。'\n        });\n        API.registerSetting({\n            type: \"switch\",\n            key: \"watchlater\",\n            label: \"稍后再看\",\n            value: true,\n            sort: \"rewrite\",\n            float: '重写以恢复旧版稍后再看。'\n        });\n        API.registerSetting({\n            type: \"switch\",\n            key: \"history\",\n            label: \"只显示视频历史\",\n            sub: \"去除专栏、直播记录\",\n            value: false,\n            sort: \"style\"\n        });\n        API.registerSetting({\n            type: \"switch\",\n            key: \"searchHistory\",\n            label: \"去除历史记录页面搜索框\",\n            sub: \"其实留着也没什么\",\n            value: false,\n            sort: \"style\"\n        });\n        API.registerSetting({\n            type: \"switch\",\n            key: \"liveStream\",\n            label: \"拦截直播流/轮播流\",\n            sub: \"那我为什么点开直播?\",\n            value: false,\n            sort: \"live\",\n            float: \"将直播间设为未开播状态,不加载直播流或者轮播视频,适用于想打开直播间但不想浪费带宽或流量的情况。</br>※ 脚本注入不够快时可能拦截失败,硬刷新`Ctrl+Shift+R`/`Shift + F5`可解。\"\n        });\n        API.registerSetting({\n            type: \"switch\",\n            key: \"liveP2p\",\n            label: \"禁止P2P上传\",\n            sub: \"小水管禁不起别人白嫖!\",\n            value: true,\n            sort: \"live\",\n            float: \"禁止直播间使用WebRTC进行P2P共享上传,以免暴露ip地址,并为小水管节约带宽。\"\n        });\n        API.registerSetting({\n            type: \"switch\",\n            key: \"sleepCheck\",\n            label: \"禁止挂机检测\",\n            sub: \"就喜欢挂后台听个响不行吗!\",\n            value: true,\n            sort: \"live\",\n            float: \"禁止直播间5分钟不操作判定挂机并切断直播,可以放心挂后台听个响。\"\n        });\n        API.registerSetting({\n            type: \"switch\",\n            key: \"anchor\",\n            label: \"禁用天选时刻\",\n            sub: \"反正中不了的,哼!\",\n            value: false,\n            sort: \"live\"\n        });\n        API.registerSetting({\n            type: \"switch\",\n            key: \"pkvm\",\n            label: \"禁用大乱斗\",\n            sub: \"挡着我欣赏主播了\",\n            value: false,\n            sort: \"live\"\n        });\n        API.registerSetting({\n            type: \"switch\",\n            key: \"player\",\n            label: \"嵌入\",\n            value: true,\n            sort: \"rewrite\",\n            float: '重写以恢复旧版嵌入播放器。'\n        });\n        API.registerSetting({\n            type: \"switch\",\n            key: \"ranking\",\n            label: \"排行榜\",\n            value: true,\n            sort: \"rewrite\",\n            float: \"重写以恢复旧版全站排行榜。\"\n        });\n        API.registerSetting({\n            type: \"switch\",\n            key: \"read\",\n            label: \"专栏\",\n            value: true,\n            sort: \"rewrite\",\n            float: \"重写以启用旧版专栏。\"\n        });\n        API.registerSetting({\n            type: \"switch\",\n            key: \"unloginPopover\",\n            label: \"移除未登录弹窗\",\n            sub: \"有些时候就是不喜欢登录\",\n            value: false,\n            sort: \"style\"\n        });\n        API.registerSetting({\n            key: \"downloadPicture\",\n            type: \"picture\",\n            sort: \"download\",\n            src: '//s2.hdslb.com/bfs/static/blive/blfe-album-detail/static/img/empty-hint.7b606b9.jpg',\n            hidden: !API.aid,\n            callback: function () {\n                API.aid && API.getAidInfo(API.aid).then(d => {\n                    this.innerHTML = `<picture><img src=\"${d.View.pic.replace(\"http:\", \"\")}\"></picture>`;\n                });\n            }\n        });\n        API.runWhile(() => API.aid, () => { API.changeSettingMode({ downloadPicture: false }); });\n        API.registerSetting({\n            type: \"switch\",\n            sort: \"download\",\n            key: \"downloadContentmenu\",\n            label: \"右键菜单\",\n            sub: \"播放画面上右键添加下载菜单\",\n            value: false\n        });\n        API.registerSetting({\n            type: \"mutlti\",\n            sort: \"download\",\n            key: \"downloadList\",\n            label: \"视频类型\",\n            sub: \"右键呼出下载时请求的类型\",\n            value: [\"mp4\", \"dash\", \"flv\"],\n            list: [\"mp4\", \"dash\", \"flv\"],\n            float: '下载功能会自动读取播放器已载入的视频源并呈现在下载面板上,即使未勾选对应的视频类型。</br>勾选了也不一定能获取到该类型的视频源。'\n        });\n        API.registerSetting({\n            type: \"row\",\n            sort: \"download\",\n            key: \"downloadQn\",\n            label: \"默认画质\",\n            sub: \"针对flv格式\",\n            value: 125,\n            list: [\"0\", 15, 16, 32, 48, 64, 74, 80, 112, 116, 120, 125],\n            float: '画质qn参数,数值越大画质越高,0表示自动。64(720P)以上需要登录,112(1080P+)以上需要大会员。一般只需设置为最大即可,会自动获取到能获取的最高画质。'\n        });\n        API.registerSetting({\n            type: \"row\",\n            sort: \"download\",\n            key: \"downloadMethod\",\n            label: \"下载方式\",\n            value: \"右键保存\",\n            list: [\"右键保存\", \"ef2\", \"aria2\", \"aira2 RPC\"],\n            action: (v) => {\n                switch (v) {\n                    case \"ef2\":\n                        API.alertMessage(`<a href=\"https://github.com/MotooriKashin/ef2/releases\" target=\"_blank\">EF2</a>是作者开发的一款从浏览器中拉起IDM进行下载的中间软件,可以非常方便地传递下载数据给IDM,并支持自定义文件名、保存目录等。<strong>您必须安装了ef2和IDM才能使用本方式!</strong>`).then(d => {\n                            d ? API.changeSettingMode({ referer: false, useragent: false, filepath: false, IDMLater: false, IDMToast: false, rpcServer: true, rpcPort: true, rpcToken: true, rpcTest: true }) :\n                                (config.downloadMethod = \"右键保存\", API.changeSettingMode({ referer: true, useragent: true, filepath: true, IDMLater: true, IDMToast: true, rpcServer: true, rpcPort: true, rpcToken: true, rpcTest: true }));\n                            API.displaySetting(\"downloadMethod\");\n                        });\n                        break;\n                    case \"aria2\":\n                        API.alertMessage(`aria2是一款著名的命令行下载工具,使用本方式将在您点击下载面板中的链接时将命令行复制到您的剪切板中,您可以粘贴到cmd等终端中回车进行下载。<strong>您必须先下载aria2工具并添加系统环境变量或者在终端在打开aria2二进制文件所在目录!</strong>`).then(d => {\n                            d ? API.changeSettingMode({ referer: false, useragent: false, filepath: false, IDMLater: true, IDMToast: true, rpcServer: true, rpcPort: true, rpcToken: true, rpcTest: true }) :\n                                (config.downloadMethod = \"右键保存\", API.changeSettingMode({ referer: true, useragent: true, filepath: true, IDMLate: true, IDMToast: true, rpcServer: true, rpcPort: true, rpcToken: true, rpcTest: true }));\n                            API.displaySetting(\"downloadMethod\");\n                        });\n                        break;\n                    case \"aira2 RPC\":\n                        API.alertMessage(`aria2支持RPC方式接收下载数据,您需要在aria2配置开启RPC功能并保持后台运行,并在本脚本设置中配置好aria2主机及端口。</br>点击确定将刷新设置面板并呈现相关设置。`).then(d => {\n                            d ? API.changeSettingMode({ referer: false, useragent: false, filepath: false, IDMLater: true, IDMToast: true, rpcServer: false, rpcPort: false, rpcToken: false, rpcTest: false }) :\n                                (config.downloadMethod = \"右键保存\", API.changeSettingMode({ referer: true, useragent: true, filepath: true, IDMLater: true, IDMToast: true, rpcServer: true, rpcPort: true, rpcToken: true, rpcTest: true }));\n                            API.displaySetting(\"downloadMethod\");\n                        });\n                        break;\n                    default:\n                        API.changeSettingMode({ referer: true, useragent: true, filepath: true, IDMLater: true, IDMToast: true, rpcServer: true, rpcPort: true, rpcToken: true, rpcTest: true });\n                        API.displaySetting(\"downloadMethod\");\n                }\n            }\n        });\n        API.registerSetting({\n            type: \"input\",\n            sort: \"download\",\n            key: \"useragent\",\n            label: \"User-Agent\",\n            value: \"Bilibili Freedoooooom/MarkII\",\n            input: { type: \"text\" },\n            float: `用户代理,此值不可为空,默认使用B站客户端专属UA。`,\n            hidden: config.downloadMethod == \"右键保存\"\n        });\n        API.registerSetting({\n            type: \"input\",\n            sort: \"download\",\n            key: \"referer\",\n            label: \"referer\",\n            value: location.origin,\n            input: { type: \"text\" },\n            float: `一般为B站主域名(http://www.bilibili.com)。</br><strong>APP/TV等视频源必须为空!</strong>`,\n            hidden: config.downloadMethod == \"右键保存\"\n        });\n        API.registerSetting({\n            type: \"input\",\n            sort: \"download\",\n            key: \"filepath\",\n            label: \"保存目录\",\n            value: \"\",\n            input: { type: \"text\", placeholder: \"如:D\\\\下载\" },\n            float: 'windows端请注意反斜杠!',\n            hidden: config.downloadMethod == \"右键保存\"\n        });\n        API.registerSetting({\n            key: \"IDMLater\",\n            sort: \"download\",\n            label: \"稍后下载\",\n            sub: \"添加到IDM列表而不立即下载\",\n            type: \"switch\",\n            value: false,\n            float: \"把下载链接添加到下载列表但是不立即开始下载,需要下载时再手动到IDM里开始。<strong>B站下载链接一般都有时效,太久不下载的话链接可能失效!</strong>\",\n            hidden: config.downloadMethod != \"ef2\"\n        });\n        API.registerSetting({\n            key: \"IDMToast\",\n            sort: \"download\",\n            label: \"静默下载\",\n            sub: \"不用IDM确认框\",\n            type: \"switch\",\n            value: false,\n            float: \"禁用IDM下载前的询问弹窗,其中可以选择修改文件名及保存目录等信息。\",\n            hidden: config.downloadMethod != \"ef2\"\n        });\n        API.registerSetting({\n            key: \"rpcServer\",\n            sort: \"download\",\n            label: \"RPC主机\",\n            type: \"input\",\n            input: { type: \"url\", placeholder: \"如:http(s)://localhost\" },\n            value: \"http://localhost\",\n            hidden: config.downloadMethod != \"aira2 RPC\"\n        });\n        API.registerSetting({\n            key: \"rpcPort\",\n            sort: \"download\",\n            label: \"RPC端口\",\n            type: \"input\",\n            input: { type: \"number\", placeholder: \"如:6800\" },\n            value: 6800,\n            hidden: config.downloadMethod != \"aira2 RPC\"\n        });\n        API.registerSetting({\n            key: \"rpcToken\",\n            sort: \"download\",\n            label: \"RPC令牌(可选)\",\n            type: \"input\",\n            input: { type: \"password\" },\n            value: \"\",\n            hidden: config.downloadMethod != \"aira2 RPC\"\n        });\n        API.registerSetting({\n            key: \"rpcTest\",\n            sort: \"download\",\n            label: \"RPC调试\",\n            type: \"action\",\n            title: \"测试\",\n            hidden: config.downloadMethod != \"aira2 RPC\",\n            action: () => {\n                API.aria2.rpcTest()\n                    .then(d => toast.success(`RPC设置正常!aria2版本:${d.version}`))\n                    .catch(e => toast.error(\"RPC链接异常!请检查各项设置以及RPC主机的状况!\", e));\n            }\n        });\n        API.registerSetting({\n            key: \"dlDmCC\",\n            sort: \"download\",\n            label: \"其他下载\",\n            sub: \"弹幕、CC字幕等\",\n            type: \"sort\",\n            list: [\n                {\n                    key: \"ifDlDmCC\",\n                    sort: \"download\",\n                    label: \"弹幕、CC字幕、封面\",\n                    type: \"switch\",\n                    value: false\n                },\n                {\n                    key: \"dlDmType\",\n                    sort: \"download\",\n                    label: \"弹幕格式\",\n                    type: \"row\",\n                    value: \"xml\",\n                    list: [\"xml\", \"json\"],\n                    float: `xml是经典的B站弹幕格式,json是旧版播放器直接支持的格式,本脚本载入本地弹幕功能同时支持这两种。</br>如果只是给本脚本专用那就选json,xml对“非法字符”支持不友好,部分高级/代码/BAS弹幕可能出错。`\n                }\n            ]\n        });\n        // 旧版播放器专属设置\n        API.registerSetting({\n            key: \"onlineDanmaku\",\n            sort: \"danmaku\",\n            label: \"在线弹幕\",\n            type: \"input\",\n            float: '为当前旧版播放器载入其他站内视频弹幕,可以输入URL或者aid等参数。</br>※ 可配合选择是否合并已有弹幕。',\n            input: { type: \"url\", placeholder: \"URL\" },\n            title: \"载入\",\n            hidden: true,\n            action: (url) => {\n                var _a;\n                if (!((_a = window.player) === null || _a === void 0 ? void 0 : _a.setDanmaku))\n                    return toast.warning(\"内部组件丢失,已停止!\");\n                API.onlineDanmaku(url);\n            }\n        });\n        API.registerSetting({\n            key: \"allDanmaku\",\n            sort: \"danmaku\",\n            label: \"全弹幕装填\",\n            type: \"sort\",\n            float: '获取所有能获取的历史弹幕。</br><strong>※ 该操作耗时较长且可能造成B站临时封接口,请慎用!</strong>',\n            hidden: true,\n            list: [{\n                    key: \"allDanmakuDelay\",\n                    sort: \"danmaku\",\n                    label: \"冷却时间:/s\",\n                    type: \"input\",\n                    value: 3,\n                    input: { type: \"number\", min: 1, max: 60, step: 0.5 },\n                    float: '接口冷却时间,时间长可以降低被临时封端口的几率。'\n                },\n                {\n                    key: \"allDanmakuAction\",\n                    sort: \"danmaku\",\n                    label: \"开始获取\",\n                    type: \"action\",\n                    title: \"开始\",\n                    action: function () {\n                        var _a;\n                        if (!((_a = window.player) === null || _a === void 0 ? void 0 : _a.setDanmaku))\n                            return toast.warning(\"内部组件丢失,已停止!\");\n                        API.allDanmaku();\n                    },\n                    disabled: 0\n                }]\n        });\n        API.registerSetting({\n            key: \"localMedia\",\n            sort: \"player\",\n            label: \"载入本地文件\",\n            sub: \"视频/弹幕\",\n            type: \"file\",\n            accept: [\".mp4\", \".xml\", \".json\"],\n            float: '使用旧版播放器播放本地视频或者弹幕文件。</br>※ 视频只能为mp4格式,且编码格式被浏览器所兼容。</br>※ 若载入弹幕文件,参见弹幕设置是否合并弹幕。',\n            title: \"文件\",\n            hidden: true,\n            action: (files) => {\n                var _a;\n                (!((_a = window.player) === null || _a === void 0 ? void 0 : _a.setDanmaku)) && toast.warning(\"内部组件丢失,无法载入弹幕文件!\");\n                API.localMedia(files);\n            }\n        });\n        API.path && API.path.name && API.runWhile(() => API.path.name && window.player, () => {\n            API.changeSettingMode({ onlineDanmaku: false, allDanmaku: false, localMedia: false });\n        });\n        API.registerSetting({\n            key: \"commentLinkDetail\",\n            sort: \"style\",\n            label: \"还原评论中的超链接\",\n            sub: \"av、ss或ep\",\n            type: \"switch\",\n            value: false\n        });\n        API.registerSetting({\n            key: \"configManage\",\n            sort: \"common\",\n            svg: '<svg viewBox=\"0 0 24 24\"><g><path d=\"M3 17v2h6v-2H3zM3 5v2h10V5H3zm10 16v-2h8v-2h-8v-2h-2v6h2zM7 9v2H3v2h4v2h2V9H7zm14 4v-2H11v2h10zm-6-4h2V7h4V5h-4V3h-2v6z\"></path></g></svg>',\n            label: \"设置数据\",\n            sub: \"备份/恢复\",\n            type: \"action\",\n            title: \"管理\",\n            action: () => API.importModule(\"manage.js\", undefined, true)\n        });\n        API.registerSetting({\n            key: \"oldReplySort\",\n            sort: \"style\",\n            label: \"评论区优先展示按时间排序\",\n            sub: \"疏于维护的特别需求\",\n            type: \"switch\",\n            value: false,\n            float: \"B站曾经默认优先以时间顺序展示评论,并在最前列展示几条热评。本脚本尝试恢复过本功能,但如今已疏于维护。\"\n        });\n        API.registerSetting({\n            key: \"anime\",\n            sort: \"rewrite\",\n            label: \"番剧分区\",\n            type: \"switch\",\n            value: false,\n            float: '重写以恢复旧版番剧分区。'\n        });\n    }\n    catch (e) {\n        toast.error(\"setting.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/units/setting.js";
    modules["switchVideo.js"] = "/**\n * 本模块负责执行切P调用监听\n */\n(function () {\n    const switchlist = [];\n    /**\n     * 注册切P回调\n     * @param callback 切P时的回调函数\n     */\n    function switchVideo(callback) {\n        try {\n            if (typeof callback === \"function\")\n                switchlist.push(callback);\n        }\n        catch (e) {\n            toast.error(\"switchVideo.js\", e);\n        }\n    }\n    API.switchVideo = (callback) => switchVideo(callback);\n    API.observerAddedNodes((node) => {\n        if (/bilibili-player-area video-state-pause/.test(node.className)) {\n            switchlist.forEach(d => d());\n        }\n    });\n})();\n\n//# sourceURL=API://@bilibili/dist/units/switchVideo.js";
    modules["toast.js"] = "(function () {\n    API.registerSetting({\n        type: \"sort\",\n        key: \"toast\",\n        label: \"浮动通知\",\n        sub: '<a href=\"https://github.com/CodeSeven/toastr\">toastr</a>',\n        svg: '<svg viewBox=\"0 0 16 16\"><path d=\"M8 16a2 2 0 001.985-1.75c.017-.137-.097-.25-.235-.25h-3.5c-.138 0-.252.113-.235.25A2 2 0 008 16z\"></path><path fill-rule=\"evenodd\" d=\"M8 1.5A3.5 3.5 0 004.5 5v2.947c0 .346-.102.683-.294.97l-1.703 2.556a.018.018 0 00-.003.01l.001.006c0 .002.002.004.004.006a.017.017 0 00.006.004l.007.001h10.964l.007-.001a.016.016 0 00.006-.004.016.016 0 00.004-.006l.001-.007a.017.017 0 00-.003-.01l-1.703-2.554a1.75 1.75 0 01-.294-.97V5A3.5 3.5 0 008 1.5zM3 5a5 5 0 0110 0v2.947c0 .05.015.098.042.139l1.703 2.555A1.518 1.518 0 0113.482 13H2.518a1.518 1.518 0 01-1.263-2.36l1.703-2.554A.25.25 0 003 7.947V5z\"></path></svg>',\n        sort: \"common\",\n        list: [{\n                type: \"switch\",\n                key: \"toastcheck\",\n                label: \"通知开关\",\n                sort: \"common\",\n                value: true,\n            }, {\n                type: \"input\",\n                key: \"toasttimeout\",\n                label: \"通知时长:/s\",\n                sort: \"common\",\n                value: \"4\",\n                input: { type: \"number\", min: 1, max: 30 },\n                pattern: /^\\d+$/\n            }, {\n                type: \"input\",\n                key: \"toaststep\",\n                label: \"通知延时:/ms\",\n                sort: \"common\",\n                value: \"250\",\n                input: { type: \"number\", min: 100, max: 1000 },\n                pattern: /^\\d+$/\n            }]\n    });\n    class Toast {\n        static init() {\n            this.container = document.createElement(\"div\");\n            this.style = document.createElement(\"link\");\n            this.container.setAttribute(\"id\", \"toast-container\");\n            this.container.setAttribute(\"class\", \"toast-top-right\");\n            this.style.setAttribute(\"rel\", \"stylesheet\");\n            this.style.setAttribute(\"id\", \"toastr-style\");\n            this.style.setAttribute(\"href\", \"https://cdn.bootcdn.net/ajax/libs/toastr.js/latest/toastr.min.css\");\n        }\n        static show(type, ...msg) {\n            if (!config.toastcheck)\n                return;\n            if (!document.body) {\n                if (this.check)\n                    return;\n                return setTimeout(() => { this.check = true; this.show(type, ...msg); });\n            }\n            document.querySelector(\"#toastr-style\") || document.head.appendChild(this.style);\n            document.querySelector(\"#toast-container\") || document.body.appendChild(this.container);\n            this.box = document.querySelector(\"#toast-container\") || this.container;\n            let item = document.createElement(\"div\");\n            item.setAttribute(\"class\", \"toast toast-\" + type);\n            item.setAttribute(\"aria-live\", \"assertive\");\n            item.setAttribute(\"style\", \"visibility: hidden;position: absolute\");\n            setTimeout(() => {\n                if (this.count > 0)\n                    this.count--;\n                item = this.box.insertBefore(item, this.box.firstChild);\n                item.appendChild(this.msg(...msg));\n                this.come(item);\n                setTimeout(() => this.quit(item), (Number(config.toasttimeout) || 4) * 1000);\n            }, this.count * (Number(config.toaststep) || 250));\n            this.count++;\n        }\n        static come(item, i = 0) {\n            let height = item.clientHeight;\n            item.setAttribute(\"style\", \"display: none;\");\n            let timer = setInterval(() => {\n                i++;\n                item.setAttribute(\"style\", \"padding-top: \" + i / 4 + \"px;padding-bottom: \" + i / 4 + \"px;height: \" + i / 60 * height + \"px;\");\n                if (i === this.sence) {\n                    clearInterval(timer);\n                    item.removeAttribute(\"style\");\n                }\n            });\n        }\n        static quit(item, i = this.sence) {\n            let height = item.clientHeight;\n            let timer = setInterval(() => {\n                i--;\n                item.setAttribute(\"style\", \"padding-top: \" + i / 4 + \"px;padding-bottom: \" + i / 4 + \"px;height: \" + i / 60 * height + \"px;\");\n                if (i === 0) {\n                    clearInterval(timer);\n                    item.remove();\n                    if (!this.box.firstChild)\n                        this.box.remove();\n                }\n            });\n        }\n        static msg(...msg) {\n            let div = document.createElement(\"div\");\n            div.setAttribute(\"class\", \"toast-message\");\n            div.innerHTML = msg.reduce((s, d, i) => {\n                s = s + (i ? \"<br />\" : \"\") + String(d);\n                return s;\n            }, \"\");\n            return div;\n        }\n    }\n    /**\n     * 未呈现通知计数\n     */\n    Toast.count = 0;\n    /**\n     * 动画呈现帧数\n     */\n    Toast.sence = 60;\n    Toast.init();\n    // @ts-ignore\n    API.toast = (...msg) => { debug.debug(...msg); Toast.show(\"info\", ...msg); };\n    Reflect.set(Reflect.get(API, \"toast\"), \"info\", (...msg) => { debug.debug(...msg); Toast.show(\"info\", ...msg); });\n    Reflect.set(Reflect.get(API, \"toast\"), \"success\", (...msg) => { debug.log(...msg); Toast.show(\"success\", ...msg); });\n    Reflect.set(Reflect.get(API, \"toast\"), \"warning\", (...msg) => { debug.warn(...msg); Toast.show(\"warning\", ...msg); });\n    Reflect.set(Reflect.get(API, \"toast\"), \"error\", (...msg) => { debug.error(...msg); Toast.show(\"error\", ...msg); });\n})();\n\n//# sourceURL=API://@bilibili/dist/units/toast.js";
    modules["ui.js"] = "/**\n * 本模块负责绘制设置UI\n */\n(function () {\n    try {\n        API.registerSetting({\n            key: \"settingEntryType\",\n            svg: '<svg viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M7.429 1.525a6.593 6.593 0 011.142 0c.036.003.108.036.137.146l.289 1.105c.147.56.55.967.997 1.189.174.086.341.183.501.29.417.278.97.423 1.53.27l1.102-.303c.11-.03.175.016.195.046.219.31.41.641.573.989.014.031.022.11-.059.19l-.815.806c-.411.406-.562.957-.53 1.456a4.588 4.588 0 010 .582c-.032.499.119 1.05.53 1.456l.815.806c.08.08.073.159.059.19a6.494 6.494 0 01-.573.99c-.02.029-.086.074-.195.045l-1.103-.303c-.559-.153-1.112-.008-1.529.27-.16.107-.327.204-.5.29-.449.222-.851.628-.998 1.189l-.289 1.105c-.029.11-.101.143-.137.146a6.613 6.613 0 01-1.142 0c-.036-.003-.108-.037-.137-.146l-.289-1.105c-.147-.56-.55-.967-.997-1.189a4.502 4.502 0 01-.501-.29c-.417-.278-.97-.423-1.53-.27l-1.102.303c-.11.03-.175-.016-.195-.046a6.492 6.492 0 01-.573-.989c-.014-.031-.022-.11.059-.19l.815-.806c.411-.406.562-.957.53-1.456a4.587 4.587 0 010-.582c.032-.499-.119-1.05-.53-1.456l-.815-.806c-.08-.08-.073-.159-.059-.19a6.44 6.44 0 01.573-.99c.02-.029.086-.075.195-.045l1.103.303c.559.153 1.112.008 1.529-.27.16-.107.327-.204.5-.29.449-.222.851-.628.998-1.189l.289-1.105c.029-.11.101-.143.137-.146zM8 0c-.236 0-.47.01-.701.03-.743.065-1.29.615-1.458 1.261l-.29 1.106c-.017.066-.078.158-.211.224a5.994 5.994 0 00-.668.386c-.123.082-.233.09-.3.071L3.27 2.776c-.644-.177-1.392.02-1.82.63a7.977 7.977 0 00-.704 1.217c-.315.675-.111 1.422.363 1.891l.815.806c.05.048.098.147.088.294a6.084 6.084 0 000 .772c.01.147-.038.246-.088.294l-.815.806c-.474.469-.678 1.216-.363 1.891.2.428.436.835.704 1.218.428.609 1.176.806 1.82.63l1.103-.303c.066-.019.176-.011.299.071.213.143.436.272.668.386.133.066.194.158.212.224l.289 1.106c.169.646.715 1.196 1.458 1.26a8.094 8.094 0 001.402 0c.743-.064 1.29-.614 1.458-1.26l.29-1.106c.017-.066.078-.158.211-.224a5.98 5.98 0 00.668-.386c.123-.082.233-.09.3-.071l1.102.302c.644.177 1.392-.02 1.82-.63.268-.382.505-.789.704-1.217.315-.675.111-1.422-.364-1.891l-.814-.806c-.05-.048-.098-.147-.088-.294a6.1 6.1 0 000-.772c-.01-.147.039-.246.088-.294l.814-.806c.475-.469.679-1.216.364-1.891a7.992 7.992 0 00-.704-1.218c-.428-.609-1.176-.806-1.82-.63l-1.103.303c-.066.019-.176.011-.299-.071a5.991 5.991 0 00-.668-.386c-.133-.066-.194-.158-.212-.224L10.16 1.29C9.99.645 9.444.095 8.701.031A8.094 8.094 0 008 0zm1.5 8a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0zM11 8a3 3 0 11-6 0 3 3 0 016 0z\"></svg>',\n            sort: \"common\",\n            type: \"switch\",\n            label: \"经典设置入口\",\n            sub: \"贴边隐藏\",\n            value: false\n        });\n        // @ts-expect-error 专属变量\n        const menu = MENU, setting = SETTING;\n        class Ui {\n            constructor() {\n                const history = GM.getValue(\"history\", {});\n                Ui.history = new Proxy(history, {\n                    set: (_target, p, value) => {\n                        history[p] = value;\n                        GM.setValue(\"history\", history);\n                        return true;\n                    },\n                    get: (_target, p) => history[p]\n                });\n                this.stage();\n            }\n            /**\n             * 设置入口\n             */\n            async stage() {\n                if (document.readyState !== 'complete') {\n                    await new Promise(r => window.addEventListener('load', r));\n                }\n                if (config.settingEntryType)\n                    return this.classical();\n                const div = API.addElement(\"div\").attachShadow({ mode: \"closed\" });\n                const stage = API.addElement(\"div\", { class: \"stage\" }, div, `<svg viewBox=\"0 0 16 16\"><path fill-rule=\"evenodd\" d=\"M7.429 1.525a6.593 6.593 0 011.142 0c.036.003.108.036.137.146l.289 1.105c.147.56.55.967.997 1.189.174.086.341.183.501.29.417.278.97.423 1.53.27l1.102-.303c.11-.03.175.016.195.046.219.31.41.641.573.989.014.031.022.11-.059.19l-.815.806c-.411.406-.562.957-.53 1.456a4.588 4.588 0 010 .582c-.032.499.119 1.05.53 1.456l.815.806c.08.08.073.159.059.19a6.494 6.494 0 01-.573.99c-.02.029-.086.074-.195.045l-1.103-.303c-.559-.153-1.112-.008-1.529.27-.16.107-.327.204-.5.29-.449.222-.851.628-.998 1.189l-.289 1.105c-.029.11-.101.143-.137.146a6.613 6.613 0 01-1.142 0c-.036-.003-.108-.037-.137-.146l-.289-1.105c-.147-.56-.55-.967-.997-1.189a4.502 4.502 0 01-.501-.29c-.417-.278-.97-.423-1.53-.27l-1.102.303c-.11.03-.175-.016-.195-.046a6.492 6.492 0 01-.573-.989c-.014-.031-.022-.11.059-.19l.815-.806c.411-.406.562-.957.53-1.456a4.587 4.587 0 010-.582c.032-.499-.119-1.05-.53-1.456l-.815-.806c-.08-.08-.073-.159-.059-.19a6.44 6.44 0 01.573-.99c.02-.029.086-.075.195-.045l1.103.303c.559.153 1.112.008 1.529-.27.16-.107.327-.204.5-.29.449-.222.851-.628.998-1.189l.289-1.105c.029-.11.101-.143.137-.146zM8 0c-.236 0-.47.01-.701.03-.743.065-1.29.615-1.458 1.261l-.29 1.106c-.017.066-.078.158-.211.224a5.994 5.994 0 00-.668.386c-.123.082-.233.09-.3.071L3.27 2.776c-.644-.177-1.392.02-1.82.63a7.977 7.977 0 00-.704 1.217c-.315.675-.111 1.422.363 1.891l.815.806c.05.048.098.147.088.294a6.084 6.084 0 000 .772c.01.147-.038.246-.088.294l-.815.806c-.474.469-.678 1.216-.363 1.891.2.428.436.835.704 1.218.428.609 1.176.806 1.82.63l1.103-.303c.066-.019.176-.011.299.071.213.143.436.272.668.386.133.066.194.158.212.224l.289 1.106c.169.646.715 1.196 1.458 1.26a8.094 8.094 0 001.402 0c.743-.064 1.29-.614 1.458-1.26l.29-1.106c.017-.066.078-.158.211-.224a5.98 5.98 0 00.668-.386c.123-.082.233-.09.3-.071l1.102.302c.644.177 1.392-.02 1.82-.63.268-.382.505-.789.704-1.217.315-.675.111-1.422-.364-1.891l-.814-.806c-.05-.048-.098-.147-.088-.294a6.1 6.1 0 000-.772c-.01-.147.039-.246.088-.294l.814-.806c.475-.469.679-1.216.364-1.891a7.992 7.992 0 00-.704-1.218c-.428-.609-1.176-.806-1.82-.63l-1.103.303c-.066.019-.176.011-.299-.071a5.991 5.991 0 00-.668-.386c-.133-.066-.194-.158-.212-.224L10.16 1.29C9.99.645 9.444.095 8.701.031A8.094 8.094 0 008 0zm1.5 8a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0zM11 8a3 3 0 11-6 0 3 3 0 016 0z\"></svg>`);\n                API.addCss(API.getModule(\"ui-stage.css\"), \"\", div);\n                stage.onclick = () => this.display();\n                stage.onmouseover = () => stage.style.opacity = \"0.8\";\n                setTimeout(() => {\n                    stage.style.opacity = \"0\";\n                    stage.onmouseout = () => stage.style.opacity = \"0\";\n                }, 2e3);\n            }\n            /**\n             * 经典设置入口\n             */\n            async classical() {\n                const div = API.addElement(\"div\").attachShadow({ mode: \"closed\" });\n                const classical = API.addElement(\"div\", { class: \"classical\" }, div, `<i></i><span>设置</span>`);\n                API.addCss(API.getModule(\"ui-stage.css\"), \"\", div);\n                classical.onclick = () => this.display();\n            }\n            /**\n             * 呈现设置界面\n             * @param key 设置项的key,直接滚动到对应设置\n             */\n            display(key) {\n                var _a;\n                (_a = document.querySelector(\"#ui-border-box\")) === null || _a === void 0 ? void 0 : _a.remove();\n                Ui.borderBox();\n                setting.reduce((s, d) => {\n                    d.sort && !s.includes(d.sort) && (Ui.menuitem(d.sort), s.push(d.sort));\n                    Ui.index(d);\n                    return s;\n                }, []);\n                document.body.appendChild(Ui.box);\n                Ui.tool.childNodes.forEach((d, i) => {\n                    (i < (Ui.tool.childNodes.length - 1)) && (d.style.opacity = \"0\");\n                });\n                Ui.tool.onmouseover = () => {\n                    Ui.tool.childNodes.forEach((d, i) => {\n                        (i < (Ui.tool.childNodes.length - 1)) && (d.style.opacity = \"1\");\n                    });\n                };\n                Ui.tool.onmouseout = () => {\n                    Ui.tool.childNodes.forEach((d, i) => {\n                        (i < (Ui.tool.childNodes.length - 1)) && (d.style.opacity = \"0\");\n                    });\n                };\n                key && Reflect.has(Ui.list, key) && Ui.list[key].scrollIntoView({ behavior: 'smooth', block: 'center' });\n            }\n            static borderBox() {\n                this.box = document.createElement(\"div\");\n                this.box.setAttribute(\"id\", \"ui-border-box\");\n                const root = this.box.attachShadow({ mode: \"closed\" });\n                const div = API.addElement(\"div\", { class: \"box\" }, root, `<div class=\"tool\"></div>\n            <div class=\"content\">\n                <div class=\"contain\">\n                    <div class=\"menu\"></div>\n                    <div class=\"item\"></div>\n                </div>\n            </div>`);\n                API.addCss(API.getModule(\"ui.css\"), \"\", root);\n                this.tool = div.children[0];\n                this.menu = div.children[1].children[0].children[0];\n                this.item = div.children[1].children[0].children[1];\n                this.toolIcon({\n                    type: \"icon\",\n                    svg: '<svg viewBox=\"0 0 100 100\"><path d=\"M2 2 L98 98 M 98 2 L2 98Z\" stroke-width=\"10px\" stroke=\"#212121\" stroke-linecap=\"round\"></path></svg>',\n                    title: \"关闭\",\n                    action: (node) => node.remove()\n                });\n            }\n            /**\n             * 添加工具栏按钮\n             * @param obj 按钮配置数据\n             */\n            static toolIcon(obj) {\n                const div = this.icon(obj.svg);\n                div.setAttribute(\"title\", obj.title);\n                this.tool.insertBefore(div, this.tool.firstChild);\n                div.onclick = () => obj.action(this.box);\n                return div;\n            }\n            /**\n             * 创建图标节点\n             * @param svg 图标 svg 字符串\n             * @returns 图标节点\n             */\n            static icon(svg) {\n                const div = document.createElement(\"div\");\n                const root = div.attachShadow({ mode: \"closed\" });\n                API.addElement(\"div\", { class: \"icon\" }, root, svg);\n                API.addCss(API.getModule(\"icon.css\"), \"\", root);\n                return div;\n            }\n            /**\n             * 添加菜单栏\n             * @param key 菜单主键\n             */\n            static menuitem(key) {\n                let obj = menu[key];\n                const div = API.addElement(\"div\", {}, this.menu);\n                const root = div.attachShadow({ mode: \"closed\" });\n                const real = API.addElement(\"div\", { class: \"menuitem\" }, root);\n                API.addCss(API.getModule(\"ui-menu.css\"), \"\", root);\n                obj.svg && real.appendChild(this.icon(obj.svg));\n                real.appendChild(document.createTextNode(obj.name));\n                div.onclick = () => {\n                    let selected = this.menu.querySelector(\".selected\");\n                    let itembox = this.item.querySelector(`.${obj.key}`);\n                    selected && selected.removeAttribute(\"class\");\n                    itembox && itembox.scrollIntoView({ behavior: 'smooth', block: 'center' });\n                    div.setAttribute(\"class\", \"selected\");\n                };\n            }\n            /**\n             * 添加菜单组合项\n             * @param key 菜单主键\n             * @returns 组合框节点,用以添加设计设置项\n             */\n            static itemContain(key) {\n                let obj = menu[key];\n                let div = this.item.querySelector(`.${obj.key}`);\n                if (!div) {\n                    div = API.addElement(\"div\", { class: obj.key }, this.item);\n                    const root = div.attachShadow({ mode: \"open\" });\n                    API.addElement(\"div\", { class: \"contain\" }, root, `<div class=\"header\">\n                    <h2 class=\"title\">${obj.name}</h2>\n                </div>\n                <div class=\"card\"></div>`);\n                    API.addCss(API.getModule(\"ui-contain.css\"), \"\", root);\n                }\n                return div.shadowRoot.querySelector(\".card\");\n            }\n            /**\n             * 创建浮动信息,鼠标移动该节点上时显示\n             * @param node 浮动信息所属节点\n             * @param data 浮动信息内容\n             */\n            static float(node, data) {\n                const div = document.createElement(\"div\");\n                const root = div.attachShadow({ mode: \"closed\" });\n                const real = API.addElement(\"div\", { class: \"float\" }, root, `<div class=\"arrow\"></div><div class=\"message\">${data}</div>`);\n                API.addCss(API.getModule(\"ui-float.css\"), \"\", root);\n                node.onmouseover = (ev) => {\n                    document.body.appendChild(div);\n                    let rect = real.getBoundingClientRect();\n                    real.style.left = `${node.getBoundingClientRect().x + ev.offsetX}px`;\n                    real.style.top = `${node.getBoundingClientRect().y + ev.offsetY - rect.height}px`;\n                    real.style.width = `${Math.sqrt(rect.width * rect.height) * 4 / 3}px`;\n                };\n                node.onmouseout = () => div.remove();\n            }\n            /**\n             * 设置分类\n             * @param obj 设置内容\n             * @param node 父节点\n             * @returns 设置节点\n             */\n            static index(obj, node) {\n                let result;\n                if (!obj.hidden)\n                    switch (obj.type) {\n                        case \"action\":\n                            result = this.action(obj, node);\n                            break;\n                        case \"file\":\n                            result = this.file(obj, node);\n                            break;\n                        case \"input\":\n                            result = this.input(obj, node);\n                            break;\n                        case \"mutlti\":\n                            result = this.multi(obj, node);\n                            break;\n                        case \"picture\":\n                            result = this.picture(obj, node);\n                            break;\n                        case \"row\":\n                            result = this.row(obj, node);\n                            break;\n                        case \"sort\":\n                            result = this.sort(obj, node);\n                            break;\n                        case \"switch\":\n                            result = this.switch(obj, node);\n                            break;\n                        case \"icon\":\n                            result = this.toolIcon(obj);\n                            break;\n                        case \"custom\": result = this.custom(obj);\n                    }\n                return result;\n            }\n            /**\n             * 添加纯图片设置\n             * @param obj 设置内容\n             * @param node 父节点\n             * @returns 设置节点\n             */\n            static picture(obj, node) {\n                node = node || this.itemContain(obj.sort);\n                const div = document.createElement(\"div\");\n                const root = div.attachShadow({ mode: \"closed\" });\n                const real = API.addElement(\"div\", { class: \"contain\" }, root, `<picture><img src=\"${obj.src}\"></picture>`);\n                API.addCss(API.getModule(\"ui-picture.css\"), \"\", root);\n                node && node.appendChild(div);\n                obj.callback && new Promise(r => obj.callback.call(real));\n                return div;\n            }\n            /**\n             * 添加开关设置\n             * @param obj 设置内容\n             * @param node 父节点\n             * @returns 设置节点\n             */\n            static switch(obj, node) {\n                node = node || this.itemContain(obj.sort);\n                const div = document.createElement(\"div\");\n                const root = div.attachShadow({ mode: \"closed\" });\n                const real = API.addElement(\"div\", { class: \"contain\" }, root);\n                API.addCss(API.getCss(\"ui-item.css\"), \"\", root);\n                Reflect.set(this.list, obj.key, real);\n                obj.svg && real.appendChild(this.icon(obj.svg));\n                const label = API.addElement(\"div\", { class: \"label\" }, real, obj.label);\n                real.appendChild(API.element.switch(function (v) {\n                    config[obj.key] = v;\n                    obj.action && obj.action.call(this, config[obj.key]);\n                }, config[obj.key]));\n                obj.sub && (label.innerHTML = `${obj.label}<div class=\"sub\">${obj.sub}</div>`);\n                obj.float && this.float(real, obj.float);\n                node && node.appendChild(div);\n                obj.callback && new Promise(r => obj.callback.call(real));\n                return div;\n            }\n            /**\n             * 添加下拉设置\n             * @param obj 设置内容\n             * @param node 父节点\n             * @returns 设置节点\n             */\n            static row(obj, node) {\n                node = node || this.itemContain(obj.sort);\n                let div = document.createElement(\"div\");\n                const root = div.attachShadow({ mode: \"closed\" });\n                const real = API.addElement(\"div\", { class: \"contain\" }, root);\n                Reflect.set(this.list, obj.key, real);\n                API.addCss(API.getCss(\"ui-item.css\"), \"\", root);\n                obj.svg && real.appendChild(this.icon(obj.svg));\n                const label = API.addElement(\"div\", { class: \"label\" }, real, obj.label);\n                real.appendChild(API.element.select(obj.list, function (v) {\n                    config[obj.key] = v;\n                    config[obj.key] = v;\n                    obj.action && obj.action.call(this, v);\n                }, config[obj.key]));\n                obj.sub && API.addElement(\"div\", { class: \"sub\" }, label, obj.sub);\n                obj.float && this.float(real, obj.float);\n                node && node.appendChild(div);\n                obj.callback && new Promise(r => obj.callback.call(real));\n                return div;\n            }\n            /**\n             * 添加归档设置\n             * @param obj 设置内容\n             * @param node 父节点\n             * @returns 设置节点\n             */\n            static sort(obj, node) {\n                node = node || this.itemContain(obj.sort);\n                let div = document.createElement(\"div\");\n                let sec = document.createElement(\"div\");\n                let flag = false;\n                let item;\n                const root = div.attachShadow({ mode: \"closed\" });\n                const real = API.addElement(\"div\", { class: \"contain\" }, root);\n                Reflect.set(this.list, obj.key, real);\n                API.addCss(API.getModule(\"ui-sort-head.css\"), \"\", root);\n                const secroot = sec.attachShadow({ mode: \"closed\" });\n                const secreal = API.addElement(\"div\", { class: \"contain\" }, secroot);\n                API.addCss(API.getModule(\"ui-sort-body.css\"), \"\", secroot);\n                obj.svg && real.appendChild(this.icon(obj.svg));\n                const label = API.addElement(\"div\", { class: \"label\" }, real, obj.label);\n                const value = API.addElement(\"div\", { class: \"anchor\" }, real);\n                value.appendChild(this.icon(`<svg viewBox=\"0 0 24 24\"><g><path d=\"M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z\"></path></g></svg>`));\n                obj.sub && (label.innerHTML = `${obj.label}<div class=\"sub\">${obj.sub}</div>`);\n                obj.float && this.float(real, obj.float);\n                node && node.appendChild(div) && node.appendChild(sec);\n                obj.callback && new Promise(r => obj.callback.call(real));\n                item = obj.list.reduce((s, d) => {\n                    let temp = this.index(d, secreal);\n                    temp.style.display = \"none\";\n                    s.push(temp);\n                    return s;\n                }, []);\n                value.onclick = () => {\n                    flag = !flag;\n                    flag ? value.setAttribute(\"checked\", \"checked\") : value.removeAttribute(\"checked\");\n                    flag ? item.forEach(d => d.style.display = \"block\") : item.forEach(d => d.style.display = \"none\");\n                };\n                return div;\n            }\n            /**\n             * 添加按钮菜单\n             * @param obj 设置内容\n             * @param node 父节点\n             * @returns 设置节点\n             */\n            static action(obj, node) {\n                node = node || this.itemContain(obj.sort);\n                let div = document.createElement(\"div\");\n                let disabled = obj.hasOwnProperty(\"disabled\") ? obj.disabled : 3;\n                const root = div.attachShadow({ mode: \"closed\" });\n                const real = API.addElement(\"div\", { class: \"contain\" }, root);\n                Reflect.set(this.list, obj.key, real);\n                API.addCss(API.getModule(\"ui-item.css\"), \"\", root);\n                obj.svg && real.appendChild(this.icon(obj.svg));\n                const label = API.addElement(\"div\", { class: \"label\" }, real, obj.label);\n                real.appendChild(API.element.button(function () {\n                    obj.action.call(this);\n                }, obj.title, disabled));\n                obj.sub && (label.innerHTML = `${obj.label}<div class=\"sub\">${obj.sub}</div>`);\n                obj.float && this.float(real, obj.float);\n                node && node.appendChild(div);\n                obj.callback && new Promise(r => obj.callback.call(real));\n                return div;\n            }\n            /**\n             * 添加输入框设置\n             * @param obj 设置内容\n             * @param node 父节点\n             * @returns 设置节点\n             */\n            static input(obj, node) {\n                node = node || this.itemContain(obj.sort);\n                let div = document.createElement(\"div\");\n                let history = [];\n                let disabled = obj.hasOwnProperty(\"disabled\") ? obj.disabled : 3;\n                const root = div.attachShadow({ mode: \"closed\" });\n                const real = API.addElement(\"div\", { class: \"contain\" }, root);\n                Reflect.set(this.list, obj.key, real);\n                API.addCss(API.getModule(\"ui-input.css\"), \"\", root);\n                obj.svg && real.appendChild(this.icon(obj.svg));\n                API.addElement(\"div\", { style: \"padding-inline-start: 12px;flex: 1;flex-basis: 0.000000001px;padding-block-end: 12px;padding-block-start: 12px;\" }, real, obj.label);\n                const value = API.addElement(\"div\", { class: \"textbox\" }, real);\n                obj.key ? (API.addElement(\"input\", { list: `list-${obj.key}` }, value),\n                    API.addElement(\"datalist\", { id: `list-${obj.key}` }, value),\n                    value.appendChild(this.icon(`<svg viewBox=\"0 0 24 24\"><g><path d=\"M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z\"></path></g></svg>`)))\n                    : API.addElement(\"input\", {}, value);\n                obj.title && API.addElement(\"div\", { class: \"button\" }, value, obj.title);\n                (history = this.history[obj.key] || [],\n                    history.reduce((s, d) => {\n                        API.addElement(\"option\", { value: d || \"\" }, s);\n                        return s;\n                    }, value.children[1]),\n                    value.children[2].setAttribute(\"style\", \"display: none;cursor: pointer;pointer-events: auto;position: absolute;right: 100%;background-color: white;\"));\n                obj.float && this.float(real, obj.float);\n                node && node.appendChild(div);\n                obj.callback && new Promise(r => obj.callback.call(real));\n                let input = value.children[0];\n                let clear = value.children[2];\n                obj.hasOwnProperty(\"value\") && (input.value = config[obj.key]);\n                Object.entries(obj.input).forEach(d => { input.setAttribute(d[0], d[1]); });\n                value.onmouseover = () => history.length > 0 && (clear && (clear.style.display = \"block\"));\n                value.onmouseout = () => { clear && (clear.style.display = \"none\"); };\n                clear && (clear.onclick = () => {\n                    history = this.history[obj.key] = [];\n                    real.querySelectorAll(\"option\").forEach(d => d.remove());\n                    clear.style.display = \"none\";\n                });\n                obj.title ? (real.querySelector(\".button\").onclick = () => {\n                    if (!input.value || (config[obj.key] == input.value))\n                        return;\n                    if (obj.pattern && !obj.pattern.test(input.value))\n                        return toast.warning(\"非法输入!\", `正则限制:${obj.pattern.toString()}`);\n                    real.querySelector(\".button\").setAttribute(\"disabled\", \"disabled\");\n                    disabled && setTimeout(() => real.querySelector(\".button\").removeAttribute(\"disabled\"), disabled * 1000);\n                    obj.hasOwnProperty(\"value\") && (config[obj.key] = input.value, config[obj.key] = input.value);\n                    !history.includes(input.value) && history.push(input.value) && (this.history[obj.key] = history);\n                    obj.action && obj.action.call(real, input.value);\n                }) : (input.onchange = () => {\n                    if (obj.pattern && !obj.pattern.test(input.value))\n                        return toast.warning(\"非法输入!\", `正则限制:${obj.pattern.toString()}`);\n                    obj.hasOwnProperty(\"value\") && (config[obj.key] = input.value, config[obj.key] = input.value);\n                    !history.includes(input.value) && history.push(input.value) && (this.history[obj.key] = history);\n                    obj.action && obj.action.call(real, input.value);\n                });\n                return div;\n            }\n            /**\n             * 添加文件选择设置\n             * @param obj 设置内容\n             * @param node 父节点\n             * @returns 设置节点\n             */\n            static file(obj, node) {\n                node = node || this.itemContain(obj.sort);\n                let div = document.createElement(\"div\");\n                const root = div.attachShadow({ mode: \"closed\" });\n                const real = API.addElement(\"div\", { class: \"contain\" }, root);\n                Reflect.set(this.list, obj.key, real);\n                API.addCss(API.getModule(\"ui-file.css\"), \"\", root);\n                obj.svg && real.appendChild(this.icon(obj.svg));\n                const label = API.addElement(\"div\", { class: \"label\" }, real, obj.label);\n                const value = API.addElement(\"div\", { class: \"button\" }, real, obj.title);\n                const input = API.addElement(\"input\", { type: \"file\", style: \"width: 0;\" }, real);\n                obj.sub && (label.innerHTML = `${obj.label}<div class=\"sub\">${obj.sub}</div>`);\n                obj.accept && (input.accept = obj.accept.join(\",\"));\n                obj.multiple && (input.multiple = true);\n                obj.float && this.float(real, obj.float);\n                node && node.appendChild(div);\n                obj.callback && new Promise(r => obj.callback.call(real));\n                value.onclick = () => input.click();\n                input.onclick = () => input.value = \"\";\n                input.onchange = () => input.files && obj.action.call(real, input.files);\n                return div;\n            }\n            /**\n             * 添加复选设置\n             * @param obj 设置内容\n             * @param node 父节点\n             * @returns 设置节点\n             */\n            static multi(obj, node) {\n                node = node || this.itemContain(obj.sort);\n                let div = document.createElement(\"div\");\n                const root = div.attachShadow({ mode: \"closed\" });\n                const real = API.addElement(\"div\", { class: \"contain\" }, root);\n                Reflect.set(this.list, obj.key, real);\n                API.addCss(API.getModule(\"ui-item.css\"), \"\", root);\n                obj.svg && real.appendChild(this.icon(obj.svg));\n                const label = API.addElement(\"div\", { class: \"label\" }, real, obj.label);\n                real.appendChild(API.element.checkbox(obj.list, function (v) {\n                    config[obj.key] = v;\n                    obj.action && obj.action.call(this, v);\n                }, config[obj.key]));\n                obj.sub && (label.innerHTML = `${obj.label}<div class=\"sub\">${obj.sub}</div>`);\n                obj.float && this.float(real, obj.float);\n                node && node.appendChild(div);\n                obj.callback && new Promise(r => obj.callback.call(real));\n                return div;\n            }\n            /**\n             * 添加自定义设置\n             * @param obj 设置内容\n             * @param node 父节点\n             * @returns 设置节点\n             */\n            static custom(obj, node) {\n                node = node || this.itemContain(obj.sort);\n                let div = document.createElement(\"div\");\n                const root = div.attachShadow({ mode: \"open\" });\n                const real = API.addElement(\"div\", { class: \"contain\" }, root);\n                const table = {};\n                Reflect.set(this.list, obj.key, real);\n                API.addCss(API.getModule(\"ui-item.css\"), \"\", root);\n                obj.svg && real.appendChild(table.svg = this.icon(obj.svg));\n                table.label = API.addElement(\"div\", { class: \"label\" }, real, obj.label);\n                table.value = API.addElement(\"div\", {}, real, obj.custom);\n                obj.sub && (table.label.innerHTML = `${obj.label}<div class=\"sub\">${obj.sub}</div>`);\n                obj.float && this.float(real, obj.float);\n                node && node.appendChild(div);\n                obj.callback && new Promise(r => obj.callback.call(real));\n                obj.flesh && obj.flesh.call(real, new Proxy(obj, {\n                    set: (t, p, v) => {\n                        Reflect.set(obj, p, v);\n                        switch (p) {\n                            case \"svg\":\n                                table.temp = this.icon(v);\n                                table.svg.replaceWith(table.temp);\n                                table.svg = table.temp;\n                                break;\n                            case \"label\":\n                                table.label = API.addElement(\"div\", { class: \"label\" }, real, v, false, table.label);\n                                break;\n                            case \"custom\":\n                                table.value = API.addElement(\"div\", {}, real, v, false, table.value);\n                                break;\n                            case \"sub\":\n                                table.label.innerHTML = `${obj.label}<div class=\"sub\">${v}</div>`;\n                                break;\n                        }\n                        return true;\n                    }\n                }));\n                return div;\n            }\n        }\n        /**\n         * 设置项表\n         */\n        Ui.list = {};\n        API.importModule(\"setting.js\");\n        const ui = new Ui();\n        Reflect.set(API, \"displaySetting\", (key) => ui.display(key));\n        GM.getValue(\"modules\") && API.alertMessage(`脚本更新残留后残留了大量废弃数据在您本地存储中,造成了额外的性能消耗!</br>是否立即执行清洁安装?</br><strong>将删除本脚本所有存储痕迹,您可以先备份设置再执行本操作!</strong>`).then(d => {\n            if (d) {\n                const arr = GM.listValues();\n                arr.forEach(d => GM.deleteValue(d));\n                toast.success(\"清洁完成!\");\n            }\n            else\n                toast.warning(\"取消操作,将在下次刷新时重新提示!\");\n        });\n    }\n    catch (e) {\n        toast.error(\"ui.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/units/ui.js";
    modules["url.js"] = "/**\n * 本模块封装了urlAPI请求以便于访问\n */\n(function () {\n    class Url {\n        constructor() {\n            this.access_key = GM.getValue(\"access_key\", undefined);\n            /**\n             * url的默认参数,即UrlDetail未列出或可选的部分\n             */\n            this.jsonUrlDefault = {\n                \"api.bilibili.com/pgc/player/web/playurl\": { qn: 125, otype: 'json', fourk: 1 },\n                \"api.bilibili.com/x/player/playurl\": { qn: 125, otype: 'json', fourk: 1 },\n                \"interface.bilibili.com/v2/playurl\": { appkey: 9, otype: 'json', quality: 125, type: '' },\n                \"bangumi.bilibili.com/player/web_api/v2/playurl\": { appkey: 9, module: \"bangumi\", otype: 'json', quality: 125, type: '' },\n                \"api.bilibili.com/pgc/player/api/playurlproj\": { access_key: this.access_key, appkey: 0, otype: 'json', platform: 'android_i', qn: 208 },\n                \"app.bilibili.com/v2/playurlproj\": { access_key: this.access_key, appkey: 0, otype: 'json', platform: 'android_i', qn: 208 },\n                \"api.bilibili.com/pgc/player/api/playurltv\": { appkey: 6, qn: 125, fourk: 1, otype: 'json', fnver: 0, fnval: 2000, platform: \"android\", mobi_app: \"android_tv_yst\", build: 102801 },\n                \"api.bilibili.com/x/tv/ugc/playurl\": { appkey: 6, qn: 125, fourk: 1, otype: 'json', fnver: 0, fnval: 2000, platform: \"android\", mobi_app: \"android_tv_yst\", build: 102801 },\n                \"app.bilibili.com/x/intl/playurl\": { access_key: this.access_key, mobi_app: \"android_i\", fnver: 0, fnval: 2000, qn: 125, platform: \"android\", fourk: 1, build: 2100110, appkey: 0, otype: 'json', ts: new Date().getTime() },\n                \"apiintl.biliapi.net/intl/gateway/ogv/player/api/playurl\": { access_key: this.access_key, mobi_app: \"android_i\", fnver: 0, fnval: 2000, qn: 125, platform: \"android\", fourk: 1, build: 2100110, appkey: 0, otype: 'json', ts: new Date().getTime() }\n            };\n        }\n        /**\n         * 请求封装好的json请求\n         * @param url 请求的url\n         * @param detail 请求所需配置数据\n         * @param GM 是否使用跨域请求\n         * @returns Promise封装的返回值\n         */\n        getJson(url, detail, GM = false) {\n            let obj = { ...(this.jsonUrlDefault[url] || {}), ...detail };\n            Reflect.has(obj, \"appkey\") && (obj = this.sign(obj));\n            return GM ? xhr.GM({\n                url: API.objUrl(`//${url}`, obj),\n                responseType: \"json\"\n            }) : xhr({\n                url: API.objUrl(`//${url}`, obj),\n                responseType: \"json\",\n                credentials: true\n            });\n        }\n        sign(obj) {\n            return API.urlObj(`?${API.urlsign(\"\", obj, obj.appkey)}`);\n        }\n    }\n    const exports = new Url();\n    API.getJson = (url, detail, GM) => {\n        try {\n            return exports.getJson(url, detail, GM);\n        }\n        catch (e) {\n            toast.error(\"url.js\", e);\n        }\n    };\n})();\n\n//# sourceURL=API://@bilibili/dist/units/url.js";
    modules["urlInputCheck.js"] = "/**\n * 本模块负责检查url输入并返回对应aid/cid等值\n */\n(function () {\n    /**\n     * 将数据缓存起来,以免重复查询\n     */\n    const catchs = { aid: {}, ssid: {}, epid: {} };\n    API.urlInputCheck = async function (input) {\n        let aid, cid, ssid, epid, p, pgc = false;\n        toast(\"正在解析链接:\" + input);\n        if (input && !input.includes(\"?\"))\n            input = \"?\" + input; // 重整化输入便于提取参数\n        let obj = API.urlObj(input); // 获取参数对象\n        aid = input.match(/[aA][vV][0-9]+/) ? input.match(/[aA][vV][0-9]+/)[0].match(/\\d+/)[0] : undefined;\n        aid = aid || obj.aid || undefined;\n        aid = aid || (/[bB][vV]1[fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF]{9}/.test(input) ? API.abv(input.match(/[bB][vV]1[fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF]{9}/)[0]) : undefined);\n        aid = aid || (obj.bvid ? API.abv(obj.bvid) : undefined);\n        p = obj.p || 1;\n        try {\n            if (aid) {\n                if (aid == API.aid)\n                    cid = API.cid;\n                // 有缓存数据的情况\n                cid = catchs.aid[aid] && catchs.aid[aid][p - 1].cid;\n                // 直接获取到cid的情况\n                cid = cid || obj.cid || undefined;\n                if (!cid) {\n                    try {\n                        // 尝试访问B站服务器获取信息\n                        catchs.aid[aid] = API.jsonCheck(await xhr({ url: API.objUrl(\"https://api.bilibili.com/x/player/pagelist\", { \"aid\": aid }) })).data;\n                        cid = catchs.aid[aid][p - 1].cid;\n                        toast(\"正在请求av视频数据\", \"分P名称:\" + catchs.aid[aid][p - 1].part);\n                    }\n                    catch (e) {\n                        e = Array.isArray(e) ? e : [e];\n                        debug.error(\"获取视频信息出错:aid:\" + aid, \"HOST:https://api.bilibili.com/x/player/pagelist\", ...e);\n                        try {\n                            // 尝试访问BiliPlus获取信息\n                            let data = API.jsonCheck(await xhr({ url: API.objUrl(\"https://www.biliplus.com/api/view\", { \"id\": aid }) }));\n                            catchs.aid[aid] = data.list || (data.v2_app_api && data.v2_app_api.pages);\n                            cid = catchs.aid[aid][p - 1].cid;\n                            toast(\"正在请求av视频数据\", \"分P名称:\" + catchs.aid[aid][p - 1].part);\n                        }\n                        catch (e) {\n                            e = Array.isArray(e) ? e : [e];\n                            debug.error(\"获取视频信息出错:aid:\" + aid, \"HOST:https://www.biliplus.com/api/view\", ...e);\n                        }\n                    }\n                }\n            }\n            else {\n                // 输入的是番剧ss/ep链接的情况,尝试获取aid、cid\n                ssid = input.match(/[sS][sS][0-9]+/) ? input.match(/[sS][sS][0-9]+/)[0].match(/\\d+/)[0] : undefined;\n                ssid = ssid || obj.season_id || undefined;\n                epid = input.match(/[eE][pP][0-9]+/) ? input.match(/[eE][pP][0-9]+/)[0].match(/\\d+/)[0] : undefined;\n                epid = epid || obj.ep_id || undefined;\n                try {\n                    // 尝试访问bangumi接口\n                    let data;\n                    if (ssid)\n                        data = JSON.stringify(catchs.ssid[ssid]) || await xhr({ url: API.objUrl(\"https://bangumi.bilibili.com/view/web_api/season\", { season_id: ssid }) });\n                    else if (epid)\n                        data = JSON.stringify(catchs.epid[epid]) || await xhr({ url: API.objUrl(\"https://bangumi.bilibili.com/view/web_api/season\", { ep_id: epid }) });\n                    if (data) {\n                        data = API.importModule(\"bangumi-season.js\", { __INITIAL_STATE__: data, epid: epid }, true);\n                        ssid && (catchs.ssid[ssid] = data);\n                        epid && (catchs.epid[epid] = data);\n                        aid = data.epInfo.aid;\n                        cid = data.epInfo.cid;\n                        pgc = true;\n                        toast(\"正在请求Bangumi数据\", \"系列名称:\" + data.mediaInfo.title, \"分p名称:\" + data.epInfo.index_title);\n                    }\n                }\n                catch (e) {\n                    e = Array.isArray(e) ? e : [e];\n                    let data;\n                    if (epid)\n                        debug.error(\"获取视频信息出错:epid:\" + epid, \"HOST:https://bangumi.bilibili.com/view/web_api/season\", ...e);\n                    else if (ssid)\n                        debug.error(\"获取视频信息出错:ssid:\" + ssid, \"HOST:https://bangumi.bilibili.com/view/web_api/season\", ...e);\n                    try {\n                        if (epid) {\n                            data = await xhr({ url: API.objUrl(`${config.limitServer}/intl/gateway/v2/ogv/view/app/season`, { ep_id: epid }) });\n                        }\n                        else if (ssid) {\n                            data = await xhr({ url: API.objUrl(`${config.limitServer}/intl/gateway/v2/ogv/view/app/season`, { season_id: ssid }) });\n                        }\n                        data = API.importModule(\"bangumi-global.js\", { __INITIAL_STATE__: data, epid: epid }, true);\n                        aid = data.epInfo.aid;\n                        cid = data.epInfo.cid;\n                        pgc = true;\n                        toast(\"正在请求Bangumi数据\", \"系列名称:\" + data.mediaInfo.title, \"分p名称:\" + data.epInfo.index_title);\n                    }\n                    catch (e) { }\n                }\n            }\n        }\n        catch (e) {\n            toast.error(\"urlInputCheck.js\", e);\n        }\n        return { aid, cid, ssid, epid, p, pgc };\n    };\n})();\n\n//# sourceURL=API://@bilibili/dist/units/urlInputCheck.js";
    modules["vector.js"] = "/**\n * 本页面负责引导全局模块运行,一般全局生效运行的模块请将导入命令写在这里\n */\n(function () {\n    try {\n        API.initUi(); // 设置ui\n        API.importModule(\"parameterTrim.js\", { Before: false }, true); // 网址清理,重写后处理\n        API.importModule(\"infoNewNumber.js\"); // 旧版顶栏资讯数\n        config.protoDm && API.importModule(\"protoDm.js\"); // 新版弹幕\n        config.liveDm && API.importModule(\"webSocket.js\"); // 实时弹幕\n        config.logReport && API.importModule(\"logReport.js\"); // 日志拦截\n        API.importModule(\"playinfoRecord.js\"); // playinfo记录\n        API.importModule(\"unread.js\"); // 远古动态\n        API.importModule(\"autoFix.js\"); // 自动化处理\n        API.importModule(\"player-v2.js\"); // 视频信息\n        API.importModule(\"sectionTypo.js\"); // 顶栏文字\n        config.heartbeat && API.importModule(\"heartbeat.js\"); // 视频心跳\n        config.videoLimit && API.importModule(\"videoLimit.js\"); // 播放限制\n        API.importModule(\"banner.js\"); // 顶栏动图\n        config.noVideo && API.importModule(\"noVideo.js\"); // 视频拦截\n        config.replyList && API.importModule(\"replyList.js\"); // 翻页评论\n        config.section && API.importModule(\"section.js\"); // 顶栏底栏\n        config.danmakuHashId && API.path.name && API.importModule(\"danmakuHashId.js\"); // 弹幕反查\n        config.unloginPopover && !API.uid && API.importModule(\"unloginPopover.js\"); // 未登录弹窗\n        config.downloadContentmenu && API.importModule(\"contentMenu.js\"); // 下载右键菜单\n        // 自运行模块,通常是插件\n        API.importModule().forEach(d => { d.includes(\"[run]\") && API.importModule(d); });\n    }\n    catch (e) {\n        toast.error(\"vector.js\", e);\n    }\n})();\n\n//# sourceURL=API://@bilibili/dist/units/vector.js";
    modules["xhr.js"] = "(function () {\n    var _a;\n    class Xhr {\n        /**\n         * `XMLHttpRequest`的`Promise`封装\n         * @param details 以对象形式传递的参数,注意`onload`回调会覆盖Promise结果\n         * @returns `Promise`托管的请求结果或者报错信息,`async = false` 时除外,直接返回结果\n         */\n        static xhr(details) {\n            details.method == \"POST\" && (details.headers = details.headers || {}, !details.headers[\"Content-Type\"] && Reflect.set(details.headers, \"Content-Type\", \"application/x-www-form-urlencoded\"));\n            if (details.hasOwnProperty(\"async\") && Boolean(details.async) === false) {\n                let xhr = new XMLHttpRequest();\n                xhr.open(details.method || 'GET', details.url, false);\n                details.responseType && (xhr.responseType = details.responseType);\n                details.credentials && (xhr.withCredentials = true);\n                details.headers && (Object.entries(details.headers).forEach(d => xhr.setRequestHeader(d[0], d[1])));\n                details.timeout && (xhr.timeout = details.timeout);\n                xhr.send(details.data);\n                return xhr.response;\n            }\n            return new Promise((resolve, reject) => {\n                let xhr = new XMLHttpRequest();\n                xhr.open(details.method || 'GET', details.url);\n                details.responseType && (xhr.responseType = details.responseType);\n                details.headers && (Object.entries(details.headers).forEach(d => xhr.setRequestHeader(d[0], d[1])));\n                details.credentials && (xhr.withCredentials = true);\n                details.timeout && (xhr.timeout = details.timeout);\n                xhr.onabort = details.onabort || ((ev) => reject(ev));\n                xhr.onerror = details.onerror || ((ev) => reject(ev));\n                details.onloadstart && (xhr.onloadstart = details.onloadstart);\n                details.onprogress && (xhr.onprogress = details.onprogress);\n                details.onreadystatechange && (xhr.onreadystatechange = details.onreadystatechange);\n                xhr.ontimeout = details.ontimeout || ((ev) => reject(ev));\n                xhr.onload = details.onload || (() => resolve(xhr.response));\n                xhr.send(details.data);\n            });\n        }\n        /**\n         * `GM_xmlhttpRequest`的`Promise`封装,用于跨域`XMLHttpRequest`请求\n         * @param details 以对象形式传递的参数,注意`onload`回调会覆盖Promise结果\n         * @returns `Promise`托管的请求结果或者报错信息\n         */\n        static GM(details) {\n            return new Promise((resolve, reject) => {\n                details.method = details.method || 'GET';\n                details.onload = details.onload || ((xhr) => { this.catches.push([details.url, xhr.response]); resolve(xhr.response); });\n                details.onerror = details.onerror || ((xhr) => { this.catches.push([details.url, xhr.response]); reject(xhr.response); });\n                GM.xmlHttpRequest(details);\n            });\n        }\n        /**\n         * `XMLHttpRequest`的GET方法的快捷模式\n         * 将url独立为第一个参数,剩余参数放在第二个参数,方便快速发送ajax\n         * **注意本方法默认带上了cookies,如需禁用请在details中提供headers对象并将其credentials属性置为false**\n         * @param url url链接\n         * @param details url外的参数对象\n         * @returns `Promise`托管的请求结果或者报错信息,`async = false` 时除外,直接返回结果\n         */\n        static get(url, details = {}) {\n            !Reflect.has(details, \"credentials\") && (details.credentials = true);\n            // @ts-ignore\n            return this.xhr({ url: url, ...details });\n        }\n        /**\n         * `XMLHttpRequest`的POST方法的快捷模式\n         * 将url、data,Content-Type分别独立为参数,剩余参数放在末尾,方便快速发送ajax\n         * **注意本方法默认带上了cookies,如需禁用请在details中提供headers对象并将其credentials属性置为false**\n         * @param url url链接\n         * @param data post数据\n         * @param contentType 发送数据使用的编码,默认\"application/x-www-form-urlencoded\"\n         * @param details url、data外的参数对象\n         * @returns `Promise`托管的请求结果或者报错信息,`async = false` 时除外,直接返回结果\n         */\n        static post(url, data, contentType = \"application/x-www-form-urlencoded\", details = {}) {\n            !Reflect.has(details, \"credentials\") && (details.credentials = true);\n            details.headers = { \"Content-Type\": contentType, ...details.headers };\n            // @ts-ignore\n            return this.xhr({ url: url, method: \"POST\", data: data, ...details });\n        }\n    }\n    _a = Xhr;\n    Xhr.catches = [];\n    Xhr.log = () => _a.catches;\n    // @ts-ignore\n    API.xhr = (details) => Xhr.xhr(details);\n    // @ts-ignore\n    API.xhr.GM = (details) => Xhr.GM(details);\n    // @ts-ignore\n    API.xhr.log = () => Xhr.log();\n    // @ts-ignore\n    API.xhr.get = (url, details) => Xhr.get(url, details);\n    // @ts-ignore\n    API.xhr.post = (url, data, contentType, details) => Xhr.post(url, data, contentType, details);\n})();\n\n//# sourceURL=API://@bilibili/dist/units/xhr.js";
    modules["av-biliplus.js"] = "/**\n * 本模块负责重构av/BV页__INITIAL_STATE__\n * 请以`__INITIAL_STATE__`名义传入原始数据,重构结果以API对象的同名属性的形式返回\n * 原始数据对应来源`//www.biliplus.com/api/view?aid`\n * 重构__INITIAL_STATE__是非常精细的工具,请务必耐心细致\n */\n(function () {\n    const result = {\n        aid: 0,\n        comment: { count: 0, list: [] },\n        error: {},\n        isClient: false,\n        p: \"\",\n        player: \"\",\n        playurl: \"\",\n        related: [],\n        tags: [],\n        upData: {\n            face: \"https://static.hdslb.com/images/akari.jpg\",\n            name: \"\",\n            mid: 0,\n            DisplayRank: \"0\",\n            Official: { desc: \"\", role: 0, title: \"\", type: -1 },\n            approve: false,\n            archiveCount: 0,\n            article: 0,\n            attention: 10,\n            attentions: [],\n            birthday: \"\",\n            description: \"\",\n            fans: 44616,\n            friend: 10,\n            level_info: { current_exp: 0, current_level: 6, current_min: 0, next_exp: 0 },\n            nameplate: { condition: \"\", image: \"\", image_small: \"\", level: \"\", name: \"\", mid: 0 },\n            official_verify: { desc: \"\", type: -1 },\n            pendant: { expire: 0, image: \"\", image_enhance: \"\", image_enhance_frame: \"\", name: \"\", pid: 0 },\n            place: \"\",\n            rank: 10000,\n            regtime: 0,\n            sex: \"保密\",\n            sign: \"\",\n            spacesta: 0,\n            vip: { accessStatus: 0, dueRemark: \"\", theme_type: 0, vipStatus: 0, vipStatusWarn: \"\", vipType: 1 }\n        },\n        videoData: {\n            aid: 0,\n            cid: 0,\n            config: { relates_title: \"相关推荐\", share_style: 1 },\n            copyright: 2,\n            ctime: \"\",\n            desc: \"\",\n            dimension: { height: 1080, rotate: 0, width: 1920 },\n            duration: 360,\n            dynamic: \"\",\n            owner: {},\n            pages: [{ cid: 0, dimension: { height: 1080, rotate: 0, width: 1920 }, duration: 360, from: \"vupload\", page: 1, part: \"\", vid: \"\", weblink: \"\" }],\n            pic: \"\",\n            pubdate: \"\",\n            rights: { autoplay: 0, bp: 0, download: 0, elec: 0, hd5: 0, is_cooperation: 0, movie: 0, no_background: 0, no_reprint: 0, pay: 0, ugc_pay: 0, ugc_pay_preview: 0 },\n            stat: {\n                aid: 0,\n                coin: 0,\n                danmaku: 0,\n                dislike: 0,\n                favorite: 0,\n                his_rank: 0,\n                like: 0,\n                now_rank: 0,\n                reply: 0,\n                share: 0,\n                view: 0\n            },\n            state: 0,\n            tid: 0,\n            title: 0,\n            tname: 0,\n            videos: 1,\n            embedPlayer: 'EmbedPlayer(\"player\", \"//static.hdslb.com/play.swf\", \"cid=0&aid=0&pre_ad=\")'\n        }\n    };\n    // @ts-ignore:传递参数\n    let data = API.jsonCheck(__INITIAL_STATE__);\n    // 处理重定向\n    data.v2_app_api && data.v2_app_api.redirect_url && (location.href = data.v2_app_api.redirect_url);\n    data.bangumi && data.bangumi.ogv_play_url && (location.href = data.bangumi.ogv_play_url);\n    result.aid = data.aid || API.aid;\n    result.upData.name = data.author;\n    result.upData.mid = data.mid;\n    result.videoData.aid = data.aid || API.aid;\n    result.videoData.cid = data.list[0].cid;\n    result.videoData.ctime = data.created;\n    result.videoData.pubdate = data.created;\n    result.videoData.desc = data.description;\n    result.videoData.pages[0].cid = data.list[0].cid;\n    result.videoData.stat.aid = data.aid;\n    result.videoData.stat.coin = data.coins;\n    result.videoData.stat.danmaku = data.video_review;\n    result.videoData.stat.favorite = data.favorites;\n    result.videoData.stat.reply = data.review;\n    result.videoData.stat.view = data.play;\n    result.videoData.tid = data.tid;\n    result.videoData.title = data.title;\n    result.videoData.tname = data.typename;\n    data.v2_app_api && (result.tags = data.v2_app_api.tag, result.videoData = data.v2_app_api);\n    result.videoData.embedPlayer = 'EmbedPlayer(\"player\", \"//static.hdslb.com/play.swf\", \"cid=' + data.list[0].cid + '&aid=' + data.aid + '&pre_ad=\")';\n    //API.switchVideo(()=>API.debug.msg(300,\"视频已失效\",\"加载弹幕\",\"缓存信息仅供参考\",true,()=>API.importModule(\"\")))\n    API.__INITIAL_STATE__ = result;\n})();\n\n//# sourceURL=API://@bilibili/dist/__INITIAL_STATE__/av-biliplus.js";
    modules["av-detail.js"] = "/**\n * 本模块负责重构av/BV页__INITIAL_STATE__\n * 请以`__INITIAL_STATE__`名义传入原始数据,重构结果以API对象的同名属性的形式返回\n * 原始数据对应来源`//api.bilibili.com/x/web-interface/view/detail?aid`\n * 重构__INITIAL_STATE__是非常精细的工具,请务必耐心细致\n */\n(function () {\n    const result = {\n        aid: 0,\n        comment: { count: 0, list: [] },\n        error: {},\n        isClient: false,\n        p: \"\",\n        player: \"\",\n        playurl: \"\",\n        related: [],\n        tags: [],\n        upData: {\n            face: \"https://static.hdslb.com/images/akari.jpg\",\n            name: \"\",\n            mid: 0,\n            DisplayRank: \"0\",\n            Official: { desc: \"\", role: 0, title: \"\", type: -1 },\n            approve: false,\n            archiveCount: 0,\n            article: 0,\n            attention: 10,\n            attentions: [],\n            birthday: \"\",\n            description: \"\",\n            fans: 44616,\n            friend: 10,\n            level_info: { current_exp: 0, current_level: 6, current_min: 0, next_exp: 0 },\n            nameplate: { condition: \"\", image: \"\", image_small: \"\", level: \"\", name: \"\", mid: 0 },\n            official_verify: { desc: \"\", type: -1 },\n            pendant: { expire: 0, image: \"\", image_enhance: \"\", image_enhance_frame: \"\", name: \"\", pid: 0 },\n            place: \"\",\n            rank: 10000,\n            regtime: 0,\n            sex: \"保密\",\n            sign: \"\",\n            spacesta: 0,\n            vip: { accessStatus: 0, dueRemark: \"\", theme_type: 0, vipStatus: 0, vipStatusWarn: \"\", vipType: 1 }\n        },\n        videoData: {\n            aid: 0,\n            cid: 0,\n            config: { relates_title: \"相关推荐\", share_style: 1 },\n            copyright: 2,\n            ctime: \"\",\n            desc: \"\",\n            dimension: { height: 1080, rotate: 0, width: 1920 },\n            duration: 360,\n            dynamic: \"\",\n            owner: {},\n            pages: [{ cid: 0, dimension: { height: 1080, rotate: 0, width: 1920 }, duration: 360, from: \"vupload\", page: 1, part: \"\", vid: \"\", weblink: \"\" }],\n            pic: \"\",\n            pubdate: \"\",\n            rights: { autoplay: 0, bp: 0, download: 0, elec: 0, hd5: 0, is_cooperation: 0, movie: 0, no_background: 0, no_reprint: 0, pay: 0, ugc_pay: 0, ugc_pay_preview: 0 },\n            stat: {\n                aid: 0,\n                coin: 0,\n                danmaku: 0,\n                dislike: 0,\n                favorite: 0,\n                his_rank: 0,\n                like: 0,\n                now_rank: 0,\n                reply: 0,\n                share: 0,\n                view: 0\n            },\n            state: 0,\n            tid: 0,\n            title: 0,\n            tname: 0,\n            videos: 1,\n            embedPlayer: 'EmbedPlayer(\"player\", \"//static.hdslb.com/play.swf\", \"cid=0&aid=0&pre_ad=\")'\n        }\n    };\n    // @ts-ignore:传递的参数\n    let data = API.jsonCheck(__INITIAL_STATE__).data;\n    if (!data.View.cid && data.View.forward) {\n        toast.warning(\"视频撞车了!正在跳转至原视频~\");\n        location.href = `https://www.bilibili.com/video/av${data.View.forward}`;\n    }\n    result.aid = data.View.aid;\n    result.related = data.Related || [];\n    result.tags = data.Tags || [];\n    result.upData = data.Card.card || {};\n    result.upData.archiveCount = data.Card.archive_count;\n    result.videoData = data.View || {};\n    result.videoData.embedPlayer = 'EmbedPlayer(\"player\", \"//static.hdslb.com/play.swf\", \"cid=' + data.View.cid + '&aid=' + data.View.aid + '&pre_ad=\")';\n    API.__INITIAL_STATE__ = result;\n})();\n\n//# sourceURL=API://@bilibili/dist/__INITIAL_STATE__/av-detail.js";
    modules["bangumi-global.js"] = "/**\n * 本模块负责重构bangumi页__INITIAL_STATE__\n * 请以`__INITIAL_STATE__`名义传入原始数据,重构结果以API对象的同名属性的形式返回\n * 同时传入的还有以`epid`的名义指定回目,默认值为0即第一回\n * 原始数据对应来源`//api.global.bilibili.com/view/web_api/season?season_id/ep_id`\n * 重构__INITIAL_STATE__是非常精细的工具,请务必耐心细致\n */\n(function () {\n    const result = {\n        activity: {},\n        app: false,\n        area: 0,\n        canReview: true,\n        epId: 0,\n        epInfo: {},\n        epList: [],\n        epStat: { isPay: true, isVip: false, payPack: 0, status: 1, vipNeedPay: false },\n        isPlayerTrigger: false,\n        loginInfo: {},\n        mdId: 0,\n        mediaInfo: {\n            actors: \"\",\n            alias: \"\",\n            areas: [],\n            bkg_cover: \"\",\n            cover: \"\",\n            evaluate: \"\",\n            is_paster_ads: 0,\n            jp_title: \"\",\n            link: \"\",\n            media_id: 0,\n            mode: 1,\n            paster_text: \"\",\n            season_id: 0,\n            season_status: 0,\n            season_title: \"\",\n            season_type: 1,\n            square_cover: \"\",\n            staff: \"\",\n            style: [],\n            title: \"\",\n            total_ep: 0\n        },\n        mediaRating: {},\n        miniOn: 1,\n        newestEp: {},\n        paster: {},\n        payMent: {},\n        payPack: {},\n        playerRecomList: [],\n        pubInfo: {},\n        recomList: [],\n        rightsInfo: {},\n        seasonFollowed: false,\n        seasonList: [],\n        seasonStat: {},\n        special: false,\n        spending: 0,\n        sponsorTotal: { code: 0, result: { ep_bp: 0, list: [], mine: {}, users: 0 } },\n        sponsorTotalCount: 0,\n        sponsorWeek: { code: 0, result: { ep_bp: 0, list: [], mine: {}, users: 0 } },\n        ssId: 0,\n        ssStat: {},\n        upInfo: {},\n        userCoined: 1,\n        userLongReview: {},\n        userScore: -1,\n        userShortReview: {},\n        userStat: {},\n        ver: {}\n    };\n    // @ts-expect-error:传递参数\n    let epId = Number(epid) || null, data = API.jsonCheck(__INITIAL_STATE__).result;\n    let ids = [], epList = [];\n    data.modules.forEach((d) => {\n        d.data.episodes.forEach((d) => {\n            d.ctime = \"\";\n            d.duration = 1;\n            d.ep_id = d.id;\n            d.episode_status = d.status;\n            d.index = d.title;\n            d.index_title = d.long_title;\n            d.mid = 2;\n            d.page = 1;\n            d.premiere = false;\n            d.pub_real_time = \"\";\n            d.section_id = 0;\n            d.section_type = 0;\n            d.vid = \"\";\n            epList.push(d);\n            ids.push(d.id);\n        });\n    });\n    result.activity = data.activity_dialog || {};\n    result.epId = epId || ids[0];\n    result.epInfo = epId ? epList[ids.indexOf(epId)] : epList[0];\n    result.epList = epList;\n    result.mediaInfo.actors = data.actor.info;\n    result.mediaInfo.alias = data.alias;\n    result.mediaInfo.areas = data.areas;\n    result.mediaInfo.cover = data.cover;\n    result.mediaInfo.evaluate = data.evaluate;\n    result.mediaInfo.link = data.link;\n    result.mediaInfo.mode = data.mode;\n    result.mediaInfo.season_id = data.season_id;\n    result.mediaInfo.season_status = data.season_status;\n    result.mediaInfo.season_title = data.season_title;\n    result.mediaInfo.staff = data.staff;\n    result.mediaInfo.style = data.styles;\n    result.mediaInfo.title = data.title;\n    result.mediaInfo.total_ep = ids.length;\n    result.newestEp = data.new_ep;\n    result.pubInfo = data.publish;\n    result.pubInfo.is_started = 1;\n    result.rightsInfo = data.right;\n    result.seasonStat = data.stat;\n    result.ssId = data.season_id;\n    API.__INITIAL_STATE__ = result;\n})();\n\n//# sourceURL=API://@bilibili/dist/__INITIAL_STATE__/bangumi-global.js";
    modules["bangumi-season.js"] = "/**\n * 本模块负责重构bangumi页__INITIAL_STATE__\n * 请以`__INITIAL_STATE__`名义传入原始数据,重构结果以API对象的同名属性的形式返回\n * 同时传入的还有以`epid`的名义指定回目,默认值为0即第一回\n * 原始数据对应来源`//bangumi.bilibili.com/view/web_api/season?season_id/ep_id`\n * 重构__INITIAL_STATE__是非常精细的工具,请务必耐心细致\n */\n(function () {\n    const result = {\n        activity: {},\n        app: false,\n        area: 0,\n        canReview: true,\n        epId: 0,\n        epInfo: {},\n        epList: [],\n        epStat: { isPay: true, isVip: false, payPack: 0, status: 1, vipNeedPay: false },\n        isPlayerTrigger: false,\n        loginInfo: {},\n        mdId: 0,\n        mediaInfo: {\n            actors: \"\",\n            alias: \"\",\n            areas: [],\n            bkg_cover: \"\",\n            cover: \"\",\n            evaluate: \"\",\n            is_paster_ads: 0,\n            jp_title: \"\",\n            link: \"\",\n            media_id: 0,\n            mode: 1,\n            paster_text: \"\",\n            season_id: 0,\n            season_status: 0,\n            season_title: \"\",\n            season_type: 1,\n            square_cover: \"\",\n            staff: \"\",\n            style: [],\n            title: \"\",\n            total_ep: 0\n        },\n        mediaRating: {},\n        miniOn: 1,\n        newestEp: {},\n        paster: {},\n        payMent: {},\n        payPack: {},\n        playerRecomList: [],\n        pubInfo: {},\n        recomList: [],\n        rightsInfo: {},\n        seasonFollowed: false,\n        seasonList: [],\n        seasonStat: {},\n        special: false,\n        spending: 0,\n        sponsorTotal: { code: 0, result: { ep_bp: 0, list: [], mine: {}, users: 0 } },\n        sponsorTotalCount: 0,\n        sponsorWeek: { code: 0, result: { ep_bp: 0, list: [], mine: {}, users: 0 } },\n        ssId: 0,\n        ssStat: {},\n        upInfo: {},\n        userCoined: 1,\n        userLongReview: {},\n        userScore: -1,\n        userShortReview: {},\n        userStat: {},\n        ver: {}\n    };\n    // @ts-expect-error:传递参数\n    let epId = Number(epid) || null, data = API.jsonCheck(__INITIAL_STATE__).result;\n    API.vipCid = [];\n    let ids = data.episodes.reduce((s, d) => {\n        s.push(d.ep_id);\n        (d.badge == \"会员\" || d.badge_type) && API.vipCid.push(d.cid);\n        return s;\n    }, []);\n    result.activity = data.activity || {};\n    result.epId = epId || ids[0];\n    result.epInfo = data.episodes[ids.indexOf(epId)] || data.episodes[0];\n    result.epList = data.episodes;\n    result.mdId = data.media_id;\n    result.mediaInfo.actors = data.actors;\n    result.mediaInfo.alias = data.alias;\n    result.mediaInfo.areas = data.areas;\n    result.mediaInfo.bkg_cover = data.bkg_cover;\n    result.mediaInfo.cover = data.cover;\n    result.mediaInfo.evaluate = data.evaluate;\n    result.mediaInfo.is_paster_ads = data.is_paster_ads;\n    result.mediaInfo.jp_title = data.jp_title;\n    result.mediaInfo.link = data.link;\n    result.mediaInfo.media_id = data.media_id;\n    result.mediaInfo.mode = data.mode;\n    result.mediaInfo.paster_text = data.paster_text;\n    result.mediaInfo.season_id = data.season_id;\n    result.mediaInfo.season_status = data.season_status;\n    result.mediaInfo.season_title = data.season_title;\n    result.mediaInfo.season_type = data.season_type;\n    result.mediaInfo.square_cover = data.square_cover;\n    result.mediaInfo.staff = data.staff;\n    result.mediaInfo.style = data.style;\n    result.mediaInfo.title = data.title;\n    result.mediaInfo.total_ep = data.total_ep;\n    result.mediaRating = data.rating || {};\n    result.newestEp = data.newest_ep;\n    result.payMent = data.payment || {};\n    result.pubInfo = data.publish;\n    result.seasonList = data.seasons || [];\n    result.seasonStat = data.stat;\n    result.special = data.bkg_cover ? true : false;\n    result.ssId = data.season_id;\n    result.upInfo = data.up_info;\n    API.__INITIAL_STATE__ = result;\n})();\n\n//# sourceURL=API://@bilibili/dist/__INITIAL_STATE__/bangumi-season.js";
    /**
     * 初始化脚本设置数据
     */
    const CONFIG = {};
    const config = new Proxy(CONFIG, {
        set: (_target, p, value) => {
            CONFIG[p] = value;
            GM.setValue("config", CONFIG);
            return true;
        },
        get: (_target, p) => CONFIG[p]
    });
    Object.entries(GM.getValue("config", {})).forEach(k => Reflect.set(config, k[0], k[1]));
    class API {
        constructor() {
            this.GM = GM;
            this.module = [];
            this.Name = GM.info.script.name;
            this.Virsion = GM.info.script.version;
            this.Handler = [GM.info.scriptHandler, GM.info.version].join(" ");
            this.config = config;
            /**
             * 获取模块内容
             * @param name 模块名字
             * @returns json直接返回格式化对象,其他返回字符串
             */
            this.getModule = (name) => Reflect.get(modules, name);
            /**
             * 载入模块
             * @param name 模块名字
             * @param args 传递给对方的全局变量:格式{变量名:变量值}
             * @param force 是否强制载入,一般模块只会载入一次,需要二次载入请将本值设为真
             */
            this.importModule = (name, args = {}, force) => {
                if (!name)
                    return Object.keys(modules);
                if (this.module.includes(name) && !force)
                    return this.module;
                if (Reflect.has(modules, name)) {
                    !this.module.includes(name) && this.module.push(name);
                    new Function("API", "GM", "debug", "toast", "xhr", "config", "importModule", ...Object.keys(args), Reflect.get(modules, name))(API.API, GM, Reflect.get(this, "debug"), Reflect.get(this, "toast"), Reflect.get(this, "xhr"), config, this.importModule, ...Object.keys(args).reduce((s, d) => {
                        s.push(args[d]);
                        return s;
                    }, []));
                }
            };
            API.API = new Proxy(this, {
                get: (t, p) => {
                    return Reflect.get(root, p) || Reflect.get(t, p) || (Reflect.has(modules["apply.json"], p) ? (t.importModule(modules["apply.json"][p], {}),
                        Reflect.get(t, p)) : undefined);
                },
                set: (t, p, value) => {
                    Reflect.has(root, p) ? Reflect.set(root, p, value) : Reflect.set(t, p, value);
                    return true;
                }
            });
            new Function("API", Reflect.get(modules, "debug.js"))(API.API);
            new Function("API", "debug", "config", Reflect.get(modules, "toast.js"))(API.API, Reflect.get(this, "debug"), config);
            new Function("API", "GM", Reflect.get(modules, "xhr.js"))(API.API, GM);
            this.importModule("rewrite.js");
        }
        static modifyConfig(obj) {
            Reflect.has(obj, "value") && !Reflect.has(config, Reflect.get(obj, "key")) && Reflect.set(config, Reflect.get(obj, "key"), Reflect.get(obj, "value"));
            Reflect.get(obj, "type") == "sort" && Reflect.has(obj, "list") && Reflect.get(obj, "list").forEach((d) => this.modifyConfig(d));
        }
        registerSetting(obj) {
            API.SETTING.push(obj);
            API.modifyConfig(obj);
        }
        registerMenu(obj) {
            Reflect.set(API.MENU, Reflect.get(obj, "key"), obj);
        }
        changeSettingMode(mode) {
            const keys = Object.keys(mode);
            API.SETTING.forEach(d => {
                Reflect.has(d, "key") && keys.includes(Reflect.get(d, "key")) && Reflect.set(d, "hidden", Reflect.get(mode, Reflect.get(d, "key")));
            });
        }
        rewriteHTML(html) {
            this.getModule("bug.json").forEach((d) => { root[d] && Reflect.set(root, d, undefined); });
            document.open();
            document.write(html);
            document.close();
            config.rewriteMethod == "异步" && this.importModule("vector.js"); // 重写后页面正常引导
        }
        initUi() {
            root.self === root.top && this.runWhile(() => document.body, () => {
                this.importModule("ui.js", { MENU: API.MENU, SETTING: API.SETTING });
            });
            new Promise(r => delete this.initUi);
        }
    }
    API.SETTING = [];
    API.MENU = {};
    new API();
})();