// ==UserScript==
// @name 哔哩哔哩番剧出差助手
// @namespace bilibili_abroad_assistant
// @version 2.0.0
// @description 为动态页面增加显示哔哩哔哩番剧出差动态功能
// @author 溶酶菌
// @match *://t.bilibili.com
// @match *://t.bilibili.com/?*
// @icon https://www.bilibili.com/favicon.ico
// @grant GM_addStyle
// @license MIT
// @run-at document-idle
// ==/UserScript==
(function () {
'use strict';
let loaded = false // 是否已加载
let showBtn = () => document.querySelector('#show-abroad')
let hideBtn = () => document.querySelector('#hide-abroad')
let refreshBtn = () => document.querySelector('#refresh-abroad')
let backtop = () => document.querySelector("#app > div > div.home-page.f-clear > div.back-top").click()
let centerPanel = () => document.querySelector("#app > div > div.home-page.f-clear > div.home-container > div > div.center-panel")
let cardList = () => document.querySelector("#app > div > div.home-page.f-clear > div.home-container > div > div.center-panel > div.card-list")
let left = () => document.querySelector("#app > div > div.home-page.f-clear > div.home-container > div > div.left-panel > div.adaptive-scroll > div.scroll-content")
let dynamicsPanel = () => document.querySelector('#dynamics-panel')
// let loadingTips = () => document.querySelector('#loading-tips')
let dateFormat = (fmt, date) => {
let ret;
const opt = {
"Y+": date.getFullYear().toString(), // 年
"m+": (date.getMonth() + 1).toString(), // 月
"d+": date.getDate().toString(), // 日
"H+": date.getHours().toString(), // 时
"M+": date.getMinutes().toString(), // 分
"S+": date.getSeconds().toString() // 秒
// 有其他格式化字符需求可以继续添加,必须转化成字符串
};
for (let k in opt) {
ret = new RegExp("(" + k + ")").exec(fmt);
if (ret) {
fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
};
};
return fmt;
}
let loadData = function (ps = 9, pn = 1) {
// loadingTips().style.display = 'inline'
if (isNaN(pn)) {
return
}
fetch(`https://api.bilibili.com/x/space/arc/search?mid=11783021&ps=${ps}&tid=0&pn=${pn}&keyword=&order=pubdate&jsonp=jsonp`, {
method: 'GET',
credentials: 'include'
}).then(res => res.json())
.then(res => {
dynamicsPanel().innerHTML = ''
if (res.code !== 0) {
return
}
let { tlist, vlist } = res.data.list
let { pn, ps, count } = res.data.page
// loadingTips().style.display = 'none'
let listDom = document.createElement('ul')
listDom.classList.add('cube-list')
vlist.forEach(item => {
let timestamp = new Date(item.created * 1e3) // s -> ms
let itemDom = document.createElement('li')
itemDom.classList.add('small-item')
itemDom.innerHTML = `<a href="//www.bilibili.com/video/${item.bvid}" target="_blank" class="cover">
<img src="${item.pic}@380w_240h_100Q_1c.webp"
alt="${item.title}">
<span class="length">${item.length}</span>
</a>
<a href="//www.bilibili.com/video/${item.bvid}" target="_blank" title="${item.title}"
class="title">${item.title}</a>
<div class="meta"><span class="play"><i class="icon"></i>${item.play}
</span>
<span class="time" title="${dateFormat('YYYY-mm-dd HH:MM:SS', timestamp)}">
<i class="icon"></i>${dateFormat('mm-dd HH:MM', timestamp)}
</span>
</div>`
listDom.append(itemDom)
})
dynamicsPanel().append(listDom)
dynamicsPanel().append(getPageBar(ps, pn, count))
});
}
let getPageBar = (ps, pn, count) => {
let pageBarDom = document.createElement('ul')
let totalPage = Math.floor(count / ps)
let prePage = pn > 1 ? pn - 1 : undefined
let nextPage = pn < totalPage ? pn + 1 : undefined
let pageCurDom = document.createElement('li')
let pageNextDom = document.createElement('li')
let pageTotalDom = document.createElement('span')
let pageElevatorDom = document.createElement('span')
pageBarDom.classList.add('be-pager')
let pagePrev = document.createElement('li')
pagePrev.classList.add('be-pager-prev')
pagePrev.innerHTML = `<a>上一页</a>`
pagePrev.onclick = () => {
if (prePage) {
loadData(ps, prePage)
}
}
pageBarDom.append(pagePrev)
// if (prePage) {
// let prev = document.createElement('li')
// prev.classList.add('be-pager-item')
// prev.innerHTML = `<a>${prePage}</a>`
// prev.onclick = () => {
// loadData(ps, prePage)
// }
// pageBarDom.append(prev)
// }
pageCurDom.classList.add('be-pager-item')
pageCurDom.classList.add('be-pager-item-active')
pageCurDom.innerHTML = `<a>${pn}</a>`
pageBarDom.append(pageCurDom)
// if (nextPage) {
// let next = document.createElement('li')
// next.classList.add('be-pager-item')
// next.innerHTML = `<a>${nextPage}</a>`
// next.onclick = () => {
// loadData(ps, prePage)
// }
// pageBarDom.append(next)
// }
pageNextDom.classList.add('be-pager-next')
pageNextDom.innerHTML = `<a>下一页</a>`
pageNextDom.onclick = () => {
if (nextPage) {
loadData(ps, nextPage)
}
}
pageBarDom.append(pageNextDom)
pageTotalDom.classList.add('be-pager-total')
pageTotalDom.innerHTML = ` 共 ${totalPage} 页,</span>`
pageBarDom.append(pageTotalDom)
pageElevatorDom.classList.add('be-pager-options-elevator')
let span = document.createElement('span')
span.innerText = '跳转至'
pageElevatorDom.append(span)
let spaceInput = document.createElement('input')
spaceInput.classList.add('space_input')
spaceInput.setAttribute('type', 'num')
spaceInput.onkeydown = function (event) {
if (event.key === 'Enter') {
let value = Number(spaceInput.value)
if (!isNaN(value)) {
if (value > totalPage) {
spaceInput.value = totalPage
value = totalPage
}
loadData(ps, value)
}
}
}
pageElevatorDom.append(spaceInput)
span = document.createElement('span')
span.innerText = '页'
pageElevatorDom.append(span)
pageBarDom.append(pageElevatorDom)
return pageBarDom
}
let start = () => {
if (!centerPanel()) {
return
}
let panel = document.createElement('div')
panel.id = 'dynamics-panel'
panel.style.display = 'none'
panel.style.marginTop = '8px'
panel.style.backgroundColor = '#FFF'
centerPanel().append(panel)
let actionbar = document.createElement('div')
actionbar.innerHTML =
`<div style="margin-top: 8px;border-radius: 4px;position: sticky;top: 8px;background: #FFF;padding: 16px;display: flex;">
<div class="avatar" style="box-shadow: 0 0 0 1px #f25d8e;border-radius: 22px;height: 38px;width:38px;background-size: 38px 38px;background-image: url("https://i0.hdslb.com/bfs/face/9f10323503739e676857f06f5e4f5eb323e9f3f2.jpg@96w_96h_100Q_1c.webp");"></div>
<div style="margin-left: 11px;">
<div>哔哩哔哩番剧出差</div>
<div style="margin-top: 4px;font-size: 12px;color: #00b5e5">
<span id="show-abroad" style="cursor: pointer">显示</span>
<span id="hide-abroad" style="cursor: pointer;display: none">隐藏</span>
<span id="refresh-abroad" style="cursor: pointer;display: none;margin-left: 1em">刷新</span>
</div>
</div>
</div>`
left().append(actionbar)
let toggleMode = (show = true) => {
showBtn().style.display = show ? 'none' : 'inline'
hideBtn().style.display = show ? 'inline' : 'none'
refreshBtn().style.display = show ? 'inline' : 'none'
cardList().style.display = show ? 'none' : 'block'
dynamicsPanel().style.display = show ? 'block' : 'none'
backtop()
}
showBtn().onclick = () => {
toggleMode(true)
if (!loaded) {
loadData()
loaded = true
}
}
hideBtn().onclick = () => {
toggleMode(false)
}
refreshBtn().onclick = () => {
loadData()
backtop()
}
}
let sleep = function (time) {
return new Promise((resolve) => setTimeout(resolve, time));
};
// 延迟执行,否则可能找不到对应的DOM
sleep(500).then(() => {
console.log('哔哩哔哩番剧出差助手运行')
start()
})
//========================================= css
GM_addStyle(`.icon{vertical-align:middle;background-repeat:no-repeat;background-image:url(//s1.hdslb.com/bfs/static/jinkela/space/assets/icons.png)}a{color:inherit;text-decoration:none;transition:color 0.2s ease, background-color 0.2s ease}.i-watchlater{display:none;position:absolute;right:6px;bottom:4px;width:22px;height:22px;z-index:5;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAABT0lEQVQ4je3VMYrCQBTG8b/DWASLNKJgJ1hY2sloZeF2gkeYW+wZvIVXsLBJY5UdtLJLk17EIghCwChukWRxFzSaaLdfMwm8/EgemTclgOl02gEmwAAoky8RsAA+tdbrUoJ+AVZO8G9CoCeJ39Sq1+sopbBtO5e23+8xxrDdbi1gIog/vxAKYNs2Sqn0diBIenoP9X2fIAgyccv66WZZZBXvdjtc18UYkwlfJxM+n8+/1pfBefMPPw4LEZcEQcBqteJ0Or0GrlartFotLpcLnucxm83YbDbFYSEE/X6f4XBIpVLhcDjgOA6u63I8HvPDaRqNBuPxmHa7DcS7cT6f36yXj8IAUkq63S7NZpPlcomUtx9/Ck5Tq9UYjUZ3a976u0UQz9OiCcMwvYwk8XHyYYxBKXU9+p5Grybg4m1Hk9Bar4Ee4JC0JWeixOhprdffE/1yRW/TLMYAAAAASUVORK5CYII=) no-repeat}.be-tags-container{position:absolute;top:4px;right:4px}.be-tags-container .tag.new-tag{background-color:#42a0c4}.be-tags-container .tag{display:inline-block;padding:0 4px;font-size:10px;color:#fff;text-align:center;line-height:14px;border-radius:2px;margin-left:4px}.cube-list{display:flex;flex-wrap:wrap;justify-content:space-around;padding:20px;width:100%;margin-top:20px;box-sizing:border-box}.cube-list .clearfix{display:block}.cube-list .small-item{display:inline-block;width:160px;position:relative;margin:0 0 3px;padding:10px;cursor:pointer}.cube-list .small-item .length{background:#111;background:rgba(0,0,0,0.5);border-radius:5px 0 0 0;color:#fff;line-height:20px;transition:top 0.2s ease;padding:0 6px;position:absolute;right:0;bottom:0}.cube-list .small-item .cover{background:url(//s1.hdslb.com/bfs/static/jinkela/space/assets/video-placeholder.png) 50%;background-size:cover;border-radius:4px;display:block;width:160px;height:100px;overflow:hidden;position:relative}.cube-list .small-item img{border-radius:4px;display:block;width:160px;height:100px}.cube-list .small-item .title{display:block;line-height:20px;height:38px;margin-top:6px;overflow:hidden}.cube-list .small-item .meta{color:#999;white-space:nowrap;font-size:0;margin-top:6px;height:14px;line-height:14px}.cube-list .small-item .meta>span{display:inline-block;white-space:nowrap;height:14px;line-height:14px;font-size:12px;overflow:hidden}.cube-list .small-item .meta>span .icon{width:16px;height:14px;vertical-align:sub}.cube-list .small-item .meta>span:first-child{width:72px}.cube-list .small-item .play .icon{background-position:-280px -25px;display:inline-block}.cube-list .small-item .time .icon{background-position:-280px -474px;display:inline-block}.cube-list a,.cube-list abbr,.cube-list acronym,.cube-list address,.cube-list applet,.cube-list article,.cube-list aside,.cube-list audio,.cube-list b,.cube-list big,.cube-list blockquote,.cube-list body,.cube-list canvas,.cube-list caption,.cube-list center,.cube-list cite,.cube-list code,.cube-list dd,.cube-list del,.cube-list details,.cube-list dfn,.cube-list div,.cube-list dl,.cube-list dt,.cube-list em,.cube-list embed,.cube-list fieldset,.cube-list figcaption,.cube-list figure,.cube-list footer,.cube-list form,.cube-list h1,.cube-list h2,.cube-list h3,.cube-list h4,.cube-list h5,.cube-list h6,.cube-list header,.cube-list hgroup,.cube-list html,.cube-list i,.cube-list iframe,.cube-list img,.cube-list ins,.cube-list kbd,.cube-list label,.cube-list legend,.cube-list li,.cube-list mark,.cube-list menu,.cube-list nav,.cube-list object,.cube-list ol,.cube-list output,.cube-list p,.cube-list pre,.cube-list q,.cube-list ruby,.cube-list s,.cube-list samp,.cube-list section,.cube-list small,.cube-list span,.cube-list strike,.cube-list strong,.cube-list sub,.cube-list summary,.cube-list sup,.cube-list table,.cube-list tbody,.cube-list td,.cube-list tfoot,.cube-list th,.cube-list thead,.cube-list time,.cube-list tr,.cube-list tt,.cube-list u,.cube-list ul,.cube-list var,.cube-list video{margin:0;padding:0;border:0;vertical-align:baseline;word-break:break-word}.be-pager{user-select:none;padding:15px 0;text-align:center}.be-pager-disabled{display:none}.be-pager-next,.be-pager-prev{padding:0 14px;border:1px solid #d7dde4;border-radius:4px;background-color:#fff}.be-pager-item{display:inline-block;line-height:38px;padding:0 15px;margin-right:4px;text-align:center;list-style:none;background-color:#fff;-ms-user-select:none;user-select:none;cursor:pointer;font-family:Arial;font-size:14px;border:1px solid #d7dde4;border-radius:4px;transition:all 0.2s ease-in-out}.be-pager-item-jump-next,.be-pager-item-jump-prev,.be-pager-next,.be-pager-prev{display:inline-block;font-size:14px;line-height:38px;list-style:none;text-align:center;cursor:pointer;color:#666;font-family:Arial;transition:all 0.2s ease-in-out}.be-pager-next,.be-pager-prev{padding:0 14px;border:1px solid #d7dde4;border-radius:4px;background-color:#fff}.be-pager-prev{margin-right:8px}.be-pager-item a{text-decoration:none;color:#657180}.be-pager-item-active{background-color:#00a1d6;border-color:#00a1d6}.be-pager-item-active:hover a,.be-pager-item-active a{color:#fff}.be-pager-item-active:hover a,.be-pager-item-active a{color:#fff}.be-pager-total{display:inline-block;height:32px;line-height:32px;margin-left:30px;color:#99a2aa}.be-pager-options-elevator{display:inline-block;height:32px;line-height:32px;color:#99a2aa}.be-pager-options-elevator input{border-radius:4px;margin:0 8px;width:50px;outline:none}.space_input{line-height:28px;height:28px;padding:0 10px;transition:all 0.3s ease;vertical-align:top;border:1px solid #ccd0d7;border-radius:0}
`)
})();