🏠 Home 

Bilibili 动态页显示当前所有直播

显示当前所有直播


安装此脚本?
// ==UserScript==
// @name        Bilibili 动态页显示当前所有直播
// @description 显示当前所有直播
// @version     3.0
// @author      Myitian
// @license     MIT
// @namespace   myitian.bili.tPage-showMoreLives
// @match       t.bilibili.com/*
// @icon        https://www.bilibili.com/favicon.ico
// @grant       none
// ==/UserScript==
/**
* 获取 JSON
* @param {string | URL} url
* @returns {Promise<XMLHttpRequest>}
*/
function getJSON(url) {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.open('get', url, true);
xhr.withCredentials = true;
xhr.responseType = 'json';
xhr.onload = () => {
if (xhr.status == 200) {
resolve(xhr);
} else {
reject(xhr);
}
};
xhr.send();
});
}
/**
* 打开面板
*/
async function moreBtn() {
// 基底div
const base = document.createElement('div');
base.className = 'sml-base'
base.id = 'sml-base';
base.innerHTML = `
<style class="sml-style" id="sml-style">
.sml-mask {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #000;
filter: alpha(opacity=65);
-ms-filter: "alpha(opacity=65)";
opacity: .65;
z-index: 10000;
}
.sml-mainbox {
position: fixed;
top: 50%;
left: 50%;
--width: 1000px;
--height: 666px;
width: var(--width);
height: var(--height);
margin-left: calc(var(--width) / -2);
margin-top: calc(var(--height) / -2);
border-radius: 4px;
background-color: #fff;
z-index: 10001;
}
.sml-livepanel {
height: calc(100% - 58px);
width: 100%;
overflow: auto;
}
@media screen and (max-width:1030px) {
.sml-mainbox {
--width: 756px;
}
}
@media screen and (max-width:786px) {
.sml-mainbox {
--width: 512px;
}
}
@media screen and (max-width:542px) {
.sml-mainbox {
--width: 268px;
}
}
@media screen and (max-height:690px) {
.sml-mainbox {
--height: 590px;
}
}
@media screen and (max-height:614px) {
.sml-mainbox {
--height: 514px;
}
}
@media screen and (max-height:538px) {
.sml-mainbox {
--height: 438px;
}
}
@media screen and (max-height:462px) {
.sml-mainbox {
--height: 362px;
}
}
@media screen and (max-height:386px) {
.sml-mainbox {
--height: 286px;
}
}
@media screen and (max-height:310px) {
.sml-mainbox {
--height: 210px;
}
}
@media screen and (max-height:234px) {
.sml-mainbox {
--height: 134px;
}
}
.sml-title {
position: relative;
padding: 0 20px;
height: 50px;
line-height: 50px;
font-size: 16px;
color: #222;
border-bottom: 1px solid #e5e9ef;
}
.sml-icon {
position: absolute;
line-height: 50px;
width: 13px;
height: 50px;
}
.sml-refresh {
right: 60px;
background: url("data:image/png; base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALBAMAAABbgmoVAAAAJFBMVEUAAACZoqqZoqqZoqqZoqqZoqqZoqqZoqqZoqqZoqqZoqqZoqpJ643QAAAAC3RSTlMAv4DPn2AwQN+PUFHSbdYAAABLSURBVAjXY9hQvHtzAQPDpi0JKZsYGHYHMDBEL2DYoRTAwGLAICg4gYFNgAEKxBgYJgoKMJgwMARpbGBYDVK5gYEJpG8DAwPIlA0ABXgUExBfrckAAAAASUVORK5CYII=") no-repeat 50%;
cursor: pointer;
}
.sml-exit {
right: 20px;
background: url("data:image/png; base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANBAMAAACAxflPAAAAIVBMVEUAAACao6qZpa2bpKqapaqZo6qboqqapKuZoqqao6qZoqqZADmtAAAACnRSTlMA6kFUMM2Eat+9b+FOdgAAAENJREFUCNdjgAFOBSDhysDAJMTAwCIMZCsqMDgaMIAEQFyQQKEBmGZfBtHhmAjUAlLMJATmGgC1gLgQM1hBijXgxgMACcIFDbl0pdMAAAAASUVORK5CYII=") no-repeat 50%;
cursor: pointer;
}
.sml-titlesp2 {
color: #99a2aa;
letter-spacing: 0;
font-size: 14px;
}
.sml-livecontainer {
display: inline-flex;
flex-grow: 0;
flex-shrink: 0;
position: relative;
margin-bottom: 10px;
margin-top: 10px;
margin-left: 16px;
height: 56px;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
width: 224px;
}
.sml-a1 {
width: 38px;
height: 38px;
border-radius: 22px;
position: relative;
margin: 1px;
margin-right: 11px;
-ms-flex-negative: 0;
flex-shrink: 0;
background-size: cover;
background-color: #ddd;
-webkit-box-shadow: 0 0 0 1px #f25d8e;
box-shadow: 0 0 0 1px #f25d8e;
border: 1px solid #fff;
}
.sml-a2 {
text-overflow: ellipsis;
overflow: hidden;
word-break: keep-all;
max-width: 176px;
padding-right: 16px;
letter-spacing: 0;
}
.sml-upname {
font-size: 14px;
color: #222;
line-height: 20px;
max-height: 20px;
display: -webkit-box;
-webkit-line-clamp: 1;
}
.sml-areaname {
font-size: 12px;
color: #999;
line-height: 20px;
max-height: 20px;
display: -webkit-box;
-webkit-line-clamp: 1;
}
.sml-areaname:hover {
color: #23ade5
}
.sml-livename {
font-size: 12px;
color: #6d757a;
line-height: 16px;
word-break: break-all;
word-break: break-word;
text-overflow: ellipsis;
max-height: 32px;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.sml-word {
word-break: break-all;
word-break: break-word;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
overflow: hidden;
}
.sml-center {
text-align: center;
}
.sml-block {
display: block;
}
</style>
<div class="sml-mask sml-block" id="sml-mask"></div>
<div class="sml-mainbox sml-block" id="sml-mainbox">
<div class="sml-title"><!--
--><span>正在直播</span><!--
--><span class="sml-titlesp2" id="sml-titlesp2">(0)</span><!--
--><a class="sml-refresh sml-icon"></a><!--
--><a class="sml-exit sml-icon"></a><!--
--></div>
<div class="sml-livepanel sml-block" id="sml-livepanel"></div>
</div>
`;
const refresh = base.querySelector('.sml-refresh');
refresh.onclick = loadContent;
const exit = base.querySelector('.sml-exit');
exit.onclick = exitBtn;
document.body.appendChild(base);
await loadContent();
}
/**
* 加载内容
*/
async function loadContent() {
const livepanel = document.querySelector('#sml-livepanel');
livepanel.innerHTML = '';
const titlesp2 = document.querySelector('#sml-titlesp2');
let liveCount = 0;
let hasMore = true;
let page = 1;
let maxPage = 1;
while (hasMore && page <= maxPage) {
try {
const xhr = await getJSON(`https://api.live.bilibili.com/xlive/web-ucenter/user/following?page_size=29&page=${page}`);
const jsondata = xhr.response.data;
maxPage = jsondata.totalPage;
for (const user of jsondata.list) {
if (user.live_status == 0) {
hasMore = false;
break;
}
liveCount++;
const roomid = user.roomid;
const link = `https://live.bilibili.com/${roomid}`
// 容器div
const livecontainer = document.createElement('div');
livecontainer.className = 'sml-livecontainer';
// UP主头像a
const a1 = document.createElement('a');
a1.className = 'sml-block sml-a1';
a1.style = `background-image:url('${user.face}@50w_50h.png');`;
a1.href = link;
a1.target = '_blank';
// 直播信息a
const a2 = document.createElement('a');
a2.className = 'sml-block sml-a2';
a2.href = link;
a2.target = '_blank';
// UP主名称div
const upname = document.createElement('div');
upname.className = 'sml-word sml-block sml-upname';
upname.innerText = user.uname;
// 分区名称div
const areaname = document.createElement('a');
areaname.className = 'sml-word sml-block sml-areaname';
areaname.target = '_blank';
// 直播名称div
const livename = document.createElement('div');
livename.className = 'sml-word sml-block sml-livename';
livename.innerText = user.title;
getJSON(`https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom?room_id=${roomid}`).then(xhr => {
const jsondata = xhr.response.data.room_info;
// 获取房间信息
areaname.innerText = jsondata.area_name;
areaname.href = `https://live.bilibili.com/p/eden/area-tags?parentAreaId=${jsondata.parent_area_id}&areaId=${jsondata.area_id}`;
}, _ => { // 房间信息获取失败(非200)
});
a2.appendChild(upname);
a2.appendChild(areaname);
a2.appendChild(livename);
livecontainer.appendChild(a1);
livecontainer.appendChild(a2);
livepanel.appendChild(livecontainer);
}
} catch (xhr) {
const err = document.createElement('p');
err.className = 'sml-center';
err.innerText = `直播数据获取失败!(${xhr.status} ${xhr.statusText})`;
livepanel.appendChild(err);
}
page++;
titlesp2.innerText = `(${liveCount})`; // 人数
}
if (liveCount == 0) {
const err = document.createElement('p');
err.className = 'sml-center';
err.innerText = '当前无直播';
livepanel.appendChild(err);
}
}
/**
* 退出面板
*/
function exitBtn() {
document.body.removeChild(document.querySelector('#sml-base'));
}
/**
* 重新放置元素,清除事件处理器
* @param {HTMLElement} oldEelement
* @returns {HTMLElement}
*/
function replaceElement(oldEelement) {
const newElement = document.createElement(oldEelement.tagName);
for (const t of oldEelement.attributes) {
newElement.setAttribute(t.name, t.value);
}
for (const t of oldEelement.childNodes) {
newElement.appendChild(t);
}
const parent = oldEelement.parentElement;
const next = oldEelement.nextSibling;
parent.removeChild(oldEelement);
parent.insertBefore(newElement, next);
return newElement;
}
/**
* 替换按钮功能
*/
function replaceBtnFunc() {
const moreBtnEle = document.querySelector('.bili-dyn-live-users__more');
if (moreBtnEle) {
if (!document.querySelector('#sml-stop-event')) {
const moreBtnEleNew = replaceElement(moreBtnEle);
moreBtnEleNew.id = 'sml-stop-event';
moreBtnEleNew.addEventListener('click', moreBtn);
}
window.removeEventListener('keydown', replaceBtnFunc);
window.removeEventListener('mousemove', replaceBtnFunc);
window.removeEventListener('mousedown', replaceBtnFunc);
}
}
window.addEventListener('keydown', replaceBtnFunc);
window.addEventListener('mousemove', replaceBtnFunc);
window.addEventListener('mousedown', replaceBtnFunc);