/**
 * 本模块负责拓展一些小工具，这些工具不便写在主模块中
 */ /**
 * 本模块负责拓展一些小工具，这些工具不便写在主模块中
 */ ( function ( ) { try { function getCookies ( ) { return document . cookie . split ( '; ' ) . reduce ( ( s , d ) => { let key = d . split ( '=' ) [ 0 ] ; let val = d . split ( '=' ) [ 1 ] ; s [ key ] = val ; return s ; } , { } ) ; } API . getCookies = ( ) => getCookies ( ) ; async function loginExit ( referer ? ) { if ( ! API . uid ) return toast . warning ( "本就未登录，无法退出登录！" ) ; toast . warning ( "正在退出登录..." ) ; let data = API . jsonCheck ( await xhr ( { url : "https://passport.bilibili.com/login/exit/v2" , data : `biliCSRF=${ API . getCookies ( ) . bili_jct }&gourl=${ encodeURIComponent ( location . href ) }` , method : "POST" , credentials : true } ) ) ; if ( data . status ) { toast . success ( "退出登录！" ) ; if ( referer ) return location . replace ( referer ) ; setTimeout ( ( ) => location . reload ( ) , 1000 ) ; } } API . loginExit = ( referer ? ) => loginExit ( referer ) ; function jsonCheck ( data ) { let result = typeof data === "string" ? JSON . parse ( data ) : data ; if ( "code" in result && result . code !== 0 ) { let msg = result . msg || result . message || "" ; throw [ result . code , msg ] ; } return result ; } API . jsonCheck = ( data ) => jsonCheck ( data ) ; function restorePlayerSetting ( ) { let bilibili_player_settings = localStorage . getItem ( "bilibili_player_settings" ) ; let settings_copy = GM . getValue < { [ name ] : any ; } > ( "bilibili_player_settings" , { } ) ; if ( bilibili_player_settings ) { let settings = < { [ name ] : any ; } > JSON . parse ( bilibili_player_settings ) ; if ( settings ?. video_status ?. autopart !== "" ) GM . setValue < { [ name ] : any ; } > ( "bilibili_player_settings" , settings ) ; else if ( settings_copy ) localStorage . setItem ( "bilibili_player_settings" , JSON . stringify ( settings_copy ) ) ; } else if ( settings_copy ) { localStorage . setItem ( "bilibili_player_settings" , JSON . stringify ( settings_copy ) ) ; } } API . restorePlayerSetting = ( ) => restorePlayerSetting ( ) ; function biliQuickLogin ( ) { ( < any > window ) . biliQuickLogin ? ( < any > window ) . biliQuickLogin ( ) : ( < any > window ) . $ ? ( < any > window ) . $ . getScript ( "//static.hdslb.com/account/bili_quick_login.js" , ( ) => ( < any > window ) . biliQuickLogin ( ) ) : false ; } API . biliQuickLogin = ( ) => biliQuickLogin ( ) ; function getTotalTop ( node ) { var sum = 0 ; do { sum += node . offsetTop ; node = < HTMLElement > node . offsetParent ; } while ( node ) ; return sum ; } API . getTotalTop = ( node ) => getTotalTop ( node ) ; async function saveAs ( content , fileName , contentType = "text/plain" ) { const a = document . createElement ( "a" ) ; const file = new Blob ( [ content ] , { type : contentType } ) ; a . href = URL . createObjectURL ( file ) ; a . download = fileName ; a . click ( ) ; } function getUrlValue ( name ) { const reg = new RegExp ( "(^|&)" + name + "=([^&]*)(&|$)" , "i" ) ; const r = window . location . search . substr ( 1 ) . match ( reg ) ; if ( r != null ) return decodeURIComponent ( r [ 2 ] ) ; return null ; } API . getUrlValue = ( name ) => getUrlValue ( name ) ; API . saveAs = ( content , fileName , contentType ? ) => saveAs ( content , fileName , contentType ) ; function readAs ( file , type = "string" , encoding ? ) { return new Promise ( ( resolve , reject ) => { const reader = new FileReader ( ) ; switch ( type ) { case "ArrayBuffer" : reader . readAsArrayBuffer ( file ) ; break ; case "DataURL" : reader . readAsDataURL ( file ) ; break ; case "string" : reader . readAsText ( file , encoding || 'utf-8' ) ; break ; } reader . onload = ( ) => resolve ( reader . result ) ; reader . onerror = e => reject ( e ) ; } ) ; } ( < any > API . readAs ) = ( file , type ? , encoding ? ) => readAs ( file , type , encoding ) ; const aids = { } ; async function getAidInfo ( aid ) { if ( ! aids [ aid ] ) { const data = await xhr ( { url : `https://api.bilibili.com/x/web-interface/view/detail?aid=${ aid }` , responseType : "json" , credentials : true } ) ; aids [ aid ] = data . data ; } return aids [ aid ] ; } API . getAidInfo = ( aid ) => getAidInfo ( aid ) ; function strSize ( str ) { let size = 0 ; for ( let i = 0 ; i < str . length ; i ++ ) { const code = str . charCodeAt ( i ) ; if ( code <= 0x007f ) size ++ ; else if ( code <= 0x07ff ) size += 2 ; else if ( code <= 0xffff ) size += 3 ; else size += 4 ; } return size ; } API . strSize = ( str ) => strSize ( str ) ; function intervalFormat ( time ) { time >= 1e11 && ( time = Math . floor ( time / 1e3 ) ) ; const now = Math . floor ( ( new Date ) . getTime ( ) / 1e3 ) ; let t = new Date ; if ( t . setHours ( 0 ) , t . setMinutes ( 0 ) , t . setSeconds ( 0 ) , ( t = Math . floor ( t . getTime ( ) / 1e3 ) ) < time && 0 <= now - time ) { if ( now - time <= 50 ) { var r = 10 * Math . floor ( ( now - time ) % 60 / 10 ) ; return ( 10 < time ? r : 10 ) + "秒前" ; } return now - time < 3600 ? Math . floor ( ( now - time ) / 60 ) + "分钟前" : Math . floor ( ( now - time ) / 3600 ) + "小时前" ; } return API . timeFormat ( time * 1e3 , true ) ; } API . intervalFormat = ( time ) => intervalFormat ( time ) ; async function addCss ( txt , id ? , parrent ? ) { if ( ! parrent && ! document . head ) { await new Promise ( r => API . runWhile ( ( ) => document . body , r ) ) ; } parrent = parrent || document . head ; const style = document . createElement ( "style" ) ; style . setAttribute ( "type" , "text/css" ) ; id && ! ( < HTMLElement > parrent ) . querySelector ( `#${ id }` ) && style . setAttribute ( "id" , id ) ; style . appendChild ( document . createTextNode ( txt ) ) ; parrent . appendChild ( style ) ; } API . addCss = ( txt , id ? , parrent ? ) => addCss ( txt , id , parrent ) ; function addElement < T extends keyof HTMLElementTagNameMap > ( tag , attribute ? , parrent ? , innerHTML ? , top ? , replaced ? ) { let element = document . createElement ( tag ) ; attribute && ( Object . entries ( attribute ) . forEach ( d => element . setAttribute ( d [ 0 ] , d [ 1 ] ) ) ) ; parrent = parrent || document . body ; innerHTML && ( element . innerHTML = innerHTML ) ; replaced ? replaced . replaceWith ( element ) : top ? parrent . insertBefore ( element , parrent . firstChild ) : parrent . appendChild ( element ) ; return element ; } API . addElement = < T extends keyof HTMLElementTagNameMap > ( tag , attribute ? , parrent ? , innerHTML ? , top ? , replaced ? ) => addElement ( tag , attribute , parrent , innerHTML , top , replaced ) ; function runWhile ( check , callback , delay = 100 , stop = 180 ) { let timer = setInterval ( ( ) => { if ( check ( ) ) { clearInterval ( timer ) ; callback ( ) ; } } , delay ) ; stop && setTimeout ( ( ) => clearInterval ( timer ) , stop * 1000 ) ; } API . runWhile = ( check , callback , delay = 100 , stop = 180 ) => runWhile ( check , callback , delay , stop ) ; function bofqiMessage ( msg ? , time = 3 , callback ? , replace = true ) { let node = document . querySelector ( ".bilibili-player-video-toast-bottom" ) ; if ( ! node ) { if ( msg ) { if ( Array . isArray ( msg ) ) return debug . log ( ... msg ) ; return debug . log ( msg ) ; } return ; } if ( ! msg ) node . childNodes . forEach ( d => d . remove ( ) ) ; const table = document . querySelector ( ".bilibili-player-video-toast-item.bilibili-player-video-toast-pay" ) || document . createElement ( "div" ) ; table . setAttribute ( "class" , "bilibili-player-video-toast-item bilibili-player-video-toast-pay" ) ; const ele = document . createElement ( "div" ) ; ele . setAttribute ( "class" , "bilibili-player-video-toast-item-text" ) ; table . appendChild ( ele ) ; msg = Array . isArray ( msg ) ? msg : [ msg ] ; if ( ! msg [ 0 ] ) return ; replace && node . childNodes . forEach ( d => d . remove ( ) ) ; ele . innerHTML = < string > msg . reduce ( ( s , d , i ) => { if ( d ) { switch ( i ) { case 0 : s += `<span class="video-float-hint-text">${ d }</span>` ; break ; case 1 : s += `<span class="video-float-hint-btn hint-red">${ d }</span>` ; break ; case 2 : s += `<span class="video-float-hint-btn">${ d }</span>` ; break ; } } return s ; } , '' ) ; node . appendChild ( table ) ; callback && ( ele . style . cursor = "pointer" ) && ( ele . onclick = ( ) => callback ( ) ) ; ( time !== 0 ) && setTimeout ( ( ) => { ele . remove ( ) ; ! table . children [ 0 ] && table . remove ( ) ; } , time * 1000 ) ; } API . bofqiMessage = ( msg ? , time ? , callback ? , replace ? ) => bofqiMessage ( msg , time , callback , replace ) ; async function alertMessage ( text , title = API . Name ) { return new Promise ( ( r ) => { const root = API . addElement ( "div" ) ; const div = root . attachShadow ( { mode : "closed" } ) ; const table = API . addElement ( "div" , { class : "table" } , div , `
            <div class="title">${ title }</div>
            <div class="text">${ text }</div>
            <div class="act">
                <div class="button">确认</div>
                <div class="button">取消</div>
                </div>
            ` ) ; API . addCss ( API . getCss ( "alert.css" , "button.css" ) , '' , div ) ; table . querySelectorAll ( ".button" ) . forEach ( ( d , i ) => { i ? ( d . onclick = ( ) => { root . remove ( ) , r ( false ) ; } ) : ( d . onclick = ( ) => ( root . remove ( ) , r ( true ) ) ) ; } ) ; } ) ; } API . alertMessage = ( text , title ) => alertMessage ( text , title ) ; param html function rewriteHTML ( html ) { API . getModule ( "bug.json" ) . forEach ( ( d ) => { window [ d ] && Reflect . set ( window , d , undefined ) ; } ) ; ( < any > API ) . document . open ( ) ; ( < any > API ) . document . write ( html ) ; ( < any > API ) . document . close ( ) ; config . rewriteMethod == "异步" && API . importModule ( "vector.js" ) ; } API . rewriteHTML = ( html ) => rewriteHTML ( html ) ; } catch ( e ) { toast . error ( "extend.js" , e ) ; } } ) ( ) ; /**
 * 模块间的顶层变量，类似于`window`
 */ declare namespace API { /**
     * 脚本名字
     */ let Name ; /**
     * 脚本版本
     */ let Virsion ; /**
     * 脚本管理器名字
     */ let Handler ; /**
     * 获取当前用户cookies
     */ function getCookies ( ) ; param referer function loginExit ( referer ? ) ; param data function jsonCheck ( data ) ; /**
     * 修复被新版播放器数据破坏的旧版播放器设置数据
     */ function restorePlayerSetting ( ) ; /**
     * B站快捷登录
     */ function biliQuickLogin ( ) ; param node function getTotalTop ( node ) ; param content param fileName param contentType function saveAs ( content , fileName , contentType ? ) ; param file param type param encoding returns function readAs ( file ) ; function readAs ( file , type ) ; function readAs ( file , type , encoding ? ) ; function readAs ( file , type ) ; param aid function getAidInfo ( aid ) ; param name returns function getUrlValue ( name ) ; param str returns function strSize ( str ) ; param time returns function intervalFormat ( time ) ; param txt param id param parrent function addCss ( txt , id ? , parrent ? ) ; param tag param attribute param parrent param innerHTML param top param replaced function addElement < T extends keyof HTMLElementTagNameMap > ( tag , attribute ? , parrent ? , innerHTML ? , top ? , replaced ? ) ; param check param callback param delay param stop function runWhile ( check , callback , delay ? , stop ? ) ; param msg param time param callback param replace function bofqiMessage ( msg ? , time ? , callback ? , replace ? ) ; param title param text returns function alertMessage ( text , title ? ) ; param name param args param force function importModule ( name ? , args ? , force ? ) ; param name returns function getModule ( name ) ; param html function rewriteHTML ( html ) ; }