// ==UserScript==
// @name Bilibili 显示视频分区、av号等
// @namespace https://space.bilibili.com/517723/
// @version 0.01
// @description 在视频简介下方显示 分区、av 号、分P标题、动态
// @author 僠儖僲
// @include https://www.bilibili.com/video/*
// @icon https://www.bilibili.com/favicon.ico
// @compatible firefox
// @noframes
// @run-at document-start
// ==/UserScript==
(()=>{
'use strict';
const ExterminatePJAX=false
const once=(t,s,cb)=>new Promise(ok=>{
cb=e=>{t.removeEventListener(s,cb,1);ok(e)}
t.addEventListener(s,cb,1)
}),doc=document,$=doc.querySelector.bind(doc)
const root=window.unsafeWindow||window
const rAF=cb=>setTimeout(cb,500)
const waitElem=select=>new Promise((resolve,reject)=>{
const next=()=>{try{
el=$(select)
el?resolve(el):rAF(next)
}catch(e){reject(e)}}
var el;next()
})
const vueHooker=app=>new Promise((resolve,reject)=>{
const vm=app.__vue__
if(vm){resolve(vm);return}
const set=vm=>{
if(!vm)return
Object.defineProperty(app,'__vue__',{
configurable: true,
enumerable: true,
value: vm,
writable: true
})
resolve(vm)
}
Object.defineProperty(app,'__vue__',{
configurable: true,
enumerable: true,
get(){return void 0},
set(vm){set(vm)}
})
})
const menu={
set(list,cb){
if(this.list)this.clear()
this.list=list.map(title=>GM_registerMenuCommand(title,cb))
},
clear(){
this.list.forEach(id=>GM_unregisterMenuCommand(id))
this.list=null
}
}
const _call=Function.prototype.call,
saftyArrow=fn=>_call.bind(fn,null),
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').append(el)
}
return el
}
const _inject=(data)=>{
/*var el=document.querySelector('.video-data>span[title=详细信息]')
if(!el){
el=document.createElement('span')
el.title='详细信息'
el.style.margin='0 12px'
el.setAttribute('data-aid',data.aid)
document.querySelector('.video-data').append(el)
}*/
data||(data=root.__INITIAL_STATE__.videoData)
var av='av'+data.aid
var list=[
'分区:'+data.tname,av,data.bvid//,'cid='+root.cid
]
//menu.set(list,inject)
var p=location.search.match(/[?&]p=(\d+)/)
var P=p?('?p='+p[1]):''
getEl('分割线','data-title').innerText='\u3000'
getEl('详细信息').innerHTML=list.join('\u3000')
.replace(/av(\d+)(?!\w)/gi, '<a href="/video/av$1/'+P+'" target="_blank">av$1</a>')
.replace(/(bv1)(\w{9})/gi,'<a href="/video/bv1$2/'+P+'" target="_blank">$1$2</a>')
var page=data.pages[p?(p[1]-1):0]
var title=page&&page.part
getEl('分P标题').innerText=title==data.title?'分P标题与标题相同':('分P标题:'+title)
getEl('动态').innerText=data.dynamic?'-----动态-----\n'+data.dynamic:'-----动态为空-----'
}
const inject=saftyArrow(_inject)
once(doc,'DOMContentLoaded').then(async()=>{
const app=await waitElem('#app,#viewlater-app,.app-wrap')
const vm=await vueHooker(app)
const {$root}=vm,{$router}=$root
root.vm=vm
if(ExterminatePJAX){
$router.beforeEach((to,from,next)=>{
var {p}=to.query
p=p?'?p='+p:''
location.href=to.path+p
next(false)
})
}
vm.$watch('videoData',inject)
inject(vm.videoData)
})
})()