Greasy Fork

Greasy Fork is available in English.

Bilibili 显示视频分区、av号等

在视频下方显示 分区、av 号、分P标题、动态

目前为 2021-03-01 提交的版本,查看 最新版本

// ==UserScript==
// @name        Bilibili 显示视频分区、av号等
// @namespace https://space.bilibili.com/517723/
// @version        0.03
// @description 在视频下方显示 分区、av 号、分P标题、动态
// @note 才发现分区在tag里,现在会醒目显示此tag
// @author        僠儖僲
// @include        https://www.bilibili.com/video/*
// @icon        https://www.bilibili.com/favicon.ico
// @compatible firefox Firefox78-esr
// @compatible edge Edge88
// @noframes
// @grant        GM_addStyle
// @run-at        document-start
// ==/UserScript==
(()=>{
    'use strict';
    const list=['详细信息','分P标题','动态']
    const isAppend=0//为1则在简介下方
    const tname_color='#d600a1'//分区TAG颜色
    const ExterminatePJAX=false//关闭PJAX
    const root=window.unsafeWindow||window
    const vmp=(()=>{
        const globalKey='__BILIBILI_VIEWMODEL_GLOBAL_PROMISE__'
        if(root[globalKey]){return root[globalKey]}
        const _call=Function.prototype.call,etp=EventTarget.prototype
        const on=_call.bind(etp.addEventListener),off=_call.bind(etp.removeEventListener)
        const once=(t,s,cb)=>new Promise(ok=>{on(t,s,cb=e=>{off(t,s,cb,!0);ok(e)},!0)})
        const doc=document,$=doc.querySelector.bind(doc),rAF=cb=>setTimeout(cb,500)
        const waitElem=select=>new Promise((resolve,reject)=>{
            var next=el=>{try{
                (el=$(select))?resolve(el):rAF(next)
            }catch(e){reject(e)}}
            next()
        })
        const waitVm=app=>new Promise(ok=>{
            const vm=app.__vue__
            if(vm){ok(vm);return}
            const set=vm=>{
                if(!vm)return
                ok(vm)
                Object.defineProperty(app,'__vue__',{
                    configurable: true,
                    enumerable: true,
                    value: vm,
                    writable: true
                })
            }
            Object.defineProperty(app,'__vue__',{
                configurable: true,
                enumerable: true,
                get(){return void 0},
                set(vm){set(vm)}
            })
        })
        const p=once(doc,'DOMContentLoaded')
            .then(e=>waitElem('#app,#viewlater-app,.app-wrap'))
            .then(waitVm)
        p.then(vm=>{p.vm=vm})
        Object.assign(p,{on,off,once,$,waitElem,soucreName:GM_info.script.name})
        root[globalKey]=p
        return p
    })()
    const _call=Function.prototype.call,
          eventStopPropagation=_call.bind(Event.prototype.stopPropagation)
    const getEl=(value,key='title')=>{
        var el=document.querySelector(`.video-desc>.info[${key}="${value}"]`)
        if(!el){
            el=document.createElement('div')
            el.className='info open'
            el.setAttribute(key,value)
            el.setAttribute('data-old',location.href)
            el.addEventListener('click',eventStopPropagation,1)
            document.querySelector('.video-desc')[isAppend?'append':'prepend'](el)
        }
        return el
    }
    var curPart=null,curPartQuery=''
    const map={
        tnameSelect:'.s_tag .tag-area>li .tag-link[href^="//www.bilibili.com/v/"]:not([href^="//www.bilibili.com/v/channel/"])',
        ['详细信息'](el,data){
            var tnames=Array.from(document.querySelectorAll(this.tnameSelect),a=>a.innerText)
            var av='av'+data.aid
            var list=[
               tnames[1]===data.tname?tnames.join('>'):('分区:'+data.tname),av,data.bvid//,'cid='+root.cid
            ]
            el.innerHTML=list.join('\u3000')
                .replace(/av(\d+)(?!\w)/gi,`<a href="/video/av$1/${curPartQuery}" target="_blank">av$1</a>`)
                .replace(/(bv1)(\w{9})/gi,`<a href="/video/bv1$2/${curPartQuery}" target="_blank">$1$2</a>`)
        },
        ['分P标题'](el,data){
            var page=data.pages[curPart?(curPart[1]-1):0]||data.pages[0]
            var title=page&&page.part
            el.innerText=title===data.title?'分P标题与标题相同':(title?'分P标题:'+title:'分P标题为空')
        },
        eds:'—'.repeat(5),
        ['动态'](el,data){
            el.innerText=data.dynamic?`${this.eds}动态${this.eds}\n${data.dynamic}`:'————动态为空————'
        }
    }
    tname_color&&GM_addStyle(`${map.tnameSelect}{color:${tname_color};}`)
    const inject=(data)=>{
        data||(data=root.__INITIAL_STATE__.videoData)
        curPart=location.search.match(/[?&]p=(\d+)/)
        curPartQuery=curPart?('?p='+curPart[1]):''
        var b=getEl('分割线').style
        b.height='1px'
        b.backgroundColor="#e5e9f0"
        b.margin='15px 0'
        list[isAppend?'reduce':'reduceRight']((acc,cur)=>{
            map[cur](getEl(cur),data)
        },void 0)
    }
    vmp.then(vm=>{
        if(ExterminatePJAX){
            vm.$router.beforeEach((to,from,next)=>{
                var {p}=to.query
                p=p?'?p='+p:''
                location.href=to.path+p
                next(false)
            })
        }
        vm.$watch('videoData',data=>{vmp.then(()=>{inject(data)})})
        inject(vm.videoData)
    })
})()