// ==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> ></span> <span class=\"crumb\"><a href=\"//www.bilibili.com/v/douga/\">动画</a> ></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 { '<': '<', '\"': '"', '>': '>', \"'\": ''', '&': '&' }[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();
})();