人类能用的B站分P列表
// ==UserScript== // @name bilipager // @namespace http://s.xmcp.ml/ // @version 0.3.3 // @description 人类能用的B站分P列表 // @author xmcp // @match *://www.bilibili.com/video/* // @supportURL https://github.com/xmcp/bilipager // @contributionURL https://s.xmcp.ml/pakkujs/donate.png // @grant none // ==/UserScript== const ZINDEX_NORMAL=######; const ZINDEX_FULLSCREEN=2147483647; const WIDTH=350; const ANIMATION_TIME_MS=200; const CSSTEXT=` .bilipager-list::-webkit-scrollbar { width: 10px; height: 10px; } .bilipager-list::-webkit-scrollbar-track { background-color: rgba(255,255,255,.3); } .bilipager-list::-webkit-scrollbar-thumb { background-color: rgba(128,128,128,.6); } .bilipager-list::-webkit-scrollbar-thumb:active { background-color: rgba(128,128,128,1); } .bilipager-list:empty, .bilipager-popover:empty { display: none; } .bilipager-list { width: ${WIDTH}px; position: fixed; height: 100%; background-color: rgba(225,225,225,.9); top: 0; left: -${WIDTH-1}px; opacity: 0; z-index: ${ZINDEX_FULLSCREEN}; box-sizing: border-box; padding: 2em 0; overflow-y: auto; word-break: break-all; transition: left ${ANIMATION_TIME_MS}ms ease-out, opacity ${ANIMATION_TIME_MS}ms ease-out; } .bilipager-list:hover, .bilipager-list.hover { left: 0; opacity: 1; } .bilipager-list p { overflow: hidden; padding: .5em .3em .5em .5em; cursor: pointer; white-space: nowrap; transition: padding .2s ease; } .bilipager-list p code { font-family: Consolas, Courier, monospace; } .bilipager-list p span { font-size: 1.2em; } .bilipager-list p:hover { background-color: rgba(255,255,255,.8); white-space: normal; padding: .5em 0 .5em .8em; box-shadow: 0 1px 25px rgba(0,0,0,.3); } .bilipager-list p.bilipager-curp { background-color: black; color: white; } .bilipager-list p.animation { color: black; -webkit-animation: page-switch 1s ease; animation: page-switch 1s ease; } @-webkit-keyframes page-switch { 0% {box-shadow: 0 1px 25px rgba(0,0,0,.3); background-color: rgba(255,255,255,.8);} 20% {box-shadow: 0 1px 25px rgba(0,0,255,.5); background-color: rgba(205,205,255,1); } 50% {box-shadow: 0 1px 25px rgba(0,0,255,.5); background-color: rgba(205,205,255,1); } 100% {box-shadow: 0 1px 25px rgba(0,0,0,.3); background-color: rgba(255,255,255,.8);} } @keyframes page-switch { 0% {box-shadow: 0 1px 25px rgba(0,0,0,.3); background-color: rgba(255,255,255,.8);} 20% {box-shadow: 0 1px 25px rgba(0,0,255,.5); background-color: rgba(205,205,255,1); } 50% {box-shadow: 0 1px 25px rgba(0,0,255,.5); background-color: rgba(205,205,255,1); } 100% {box-shadow: 0 1px 25px rgba(0,0,0,.3); background-color: rgba(255,255,255,.8);} } .bilipager-popover { min-width: 150px; position: absolute; height: 1.7em; line-height: 1.7em; font-size: 1.2em; padding: 0 .5em; background-color: black; color: white; top: 42px; left: 10px; z-index: ${ZINDEX_NORMAL}; border-radius: 3px; word-break: break-all; white-space: nowrap; } .bilipager-popover:before { content: ""; position: absolute; width: 0; height: 0; top: 50%; left: -4px; margin-top: -5px; border-width: 5px 5px 5px 0; border-color: transparent; border-right-color: black; border-style: solid; } `; (function() { 'use strict'; let list_root=document.createElement('div'); list_root.className='bilipager-list'; list_root.addEventListener('mousewheel',function(e) { e.stopPropagation(); }); let popover=document.createElement('div'); popover.className='bilipager-popover'; popover.addEventListener('mouseover',function(e) { list_root.classList.add('hover'); setTimeout(function() { list_root.classList.remove('hover'); },ANIMATION_TIME_MS+10); }); let playlist_cache={}; function format_duration(d) { function pad(t) { return (''+t).padStart(2,'0'); } return d<3600 ? (Math.floor(d/60)+':'+pad(d%60)) : (Math.floor(d/3600)+':'+pad(Math.floor((d%3600)/60))+':'+pad(d%60)); } function reload_ui(aid) { if(!playlist_cache[aid]) { playlist_cache[aid]=fetch('https://api.bilibili.com/x/player/pagelist?aid='+aid).then(res=>res.json()); } playlist_cache[aid].then(function(plist) { list_root.textContent=''; popover.textContent=''; console.log('!!',plist); if(plist.data.length<=1) return; plist.data.forEach(function(p) { let li=document.createElement('p'); let li_1=document.createElement('code'); li_1.textContent=`[${p.page}] ${format_duration(p.duration)} `; li.appendChild(li_1); let li_2=document.createElement('span'); li_2.textContent=`${p.part}`; li.appendChild(li_2); li.addEventListener('click',function() { li.classList.add('animation'); const ind_10=Math.floor((p.page-1)/10)*10+1; const ind_30=Math.floor((p.page-1)/30)*30+1; function paginate_failed() { //alert('pagination failed'); location.href='//www.bilibili.com/video/av'+aid+'/?p='+p.page; } for(const pager_30 of document.querySelectorAll('#multi_page .more-box li')) { if(pager_30.textContent.startsWith(ind_30+'-')) { pager_30.click(); setTimeout(function() { for(const pager_10 of document.querySelectorAll('#multi_page .paging li')) { if(pager_10.textContent.startsWith(ind_10+'-')) { pager_10.click(); setTimeout(function() { const paginate_link=document.querySelector(`a.router-link-active[href="/video/av${aid}/?p=${p.page}"]`); if(paginate_link) { console.log('switch: pagniate link'); paginate_link.click(); return; } paginate_failed(); },1); return; } } paginate_failed(); },1); return; } } paginate_failed(); }); list_root.appendChild(li); if(p.cid===parseInt(window.cid)) { li.className='bilipager-curp'; if(li.scrollIntoViewIfNeeded) { li.scrollIntoViewIfNeeded(); } else { li.scrollIntoView(false); } popover.textContent=`[${p.page}/${plist.data.length}] ${p.part}`; } }); }); } function setup_listener() { function onfschange(e) { const elem=document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.body; if(list_root.parentNode!==elem) { if(list_root.parentNode) { list_root.parentNode.removeChild(list_root); } elem.appendChild(list_root); } } document.addEventListener('fullscreenchange',onfschange); document.addEventListener('webkitfullscreenchange',onfschange); document.addEventListener('mozfullscreenchange',onfschange); addEventListener('message',function(e) { if(e.data.type==='pakku_event_danmaku_loaded') { reload_ui(window.aid); } }); } if(window.aid) { let cssobj=document.createElement('style'); cssobj.textContent=CSSTEXT; document.head.appendChild(cssobj); document.body.appendChild(list_root); document.body.appendChild(popover); setup_listener(); reload_ui(window.aid); } })();