- // ==UserScript==
- // @name qb-fix-bilibili
- // @description inQ_Beta wants to fix some of bilibili problem
- // @namespace no1xsyzy
- // @match https://*.bilibili.com/*
- // @license Apache License, Version 2.0 (Apache-2.0); https://opensource.org/licenses/Apache-2.0
- // @version 0.0.6
- // @author inQ_Beta
- // @grant GM_addStyle
- // ==/UserScript==
- (function () {
- 'use strict';
-
- const $ = (x) => document.querySelector(x);
- const $$ = (x) => Array.from(document.querySelectorAll(x));
-
- function launchObserver({ parentNode, selector, failCallback = null, successCallback = null, stopWhenSuccess = true, config = {
- childList: true,
- subtree: true,
- }, }) {
- // if parent node does not exist, use body instead
- if (!parentNode) {
- parentNode = document.body;
- }
- const observeFunc = () => {
- const selected = document.querySelector(selector);
- if (!selected) {
- if (failCallback) {
- failCallback();
- }
- return;
- }
- if (stopWhenSuccess) {
- observer.disconnect();
- }
- if (successCallback) {
- successCallback(selected);
- }
- };
- const observer = new MutationObserver(observeFunc);
- observer.observe(parentNode, config);
- }
-
- function 关注栏尺寸 () {
- GM_addStyle(`.section-content-cntr{height:calc(100vh - 250px)!important;}`);
-
- launchObserver({
- selector: `.side-bar-popup-cntr.ts-dot-4`,
- successCallback: () => {
- const g = $`.side-bar-popup-cntr.ts-dot-4`;
- if (g.style.height !== '0px') {
- g.style.bottom = '75px';
- g.style.height = 'calc(100vh - 150px)';
- // g.style.height = "600px"
- }
- if ($(`.side-bar-popup-cntr.ts-dot-4 .ps`)) {
- setTimeout(() => $(`.side-bar-popup-cntr.ts-dot-4 .ps`).dispatchEvent(new Event('scroll')), 1000);
- }
- },
- stopWhenSuccess: false,
- config: {
- childList: true,
- subtree: true,
- attributes: true,
- },
- });
- }
-
- const makeTitle$1 = () =>
- `${($`#area-tags header img+div` || $`#area-tags header h2`).innerText} - 分区列表 - 哔哩哔哩直播`;
- const parentNode$3 = $`#area-tags`;
- const selector$3 = `header`;
- function 分区标题 () {
- launchObserver({
- parentNode: parentNode$3,
- selector: selector$3,
- successCallback: () => {
- document.title = makeTitle$1();
- },
- stopWhenSuccess: false,
- });
-
- document.title = makeTitle$1();
- }
-
- const TTL = 10 * 60 * 1000;
- function timedLRU1(func) {
- const cache = new Map();
- let time = [];
- let timeout = null;
- const cleanup = () => {
- if (timeout !== null) {
- clearTimeout(timeout);
- }
- const ts = new Date().getTime();
- const idx = time.findIndex(([a, t]) => t + TTL > ts);
- const drop = time.splice(idx);
- for (const [a] of drop) {
- cache.delete(a);
- }
- timeout = setTimeout(cleanup, 60 * 1000);
- };
- return (a1) => {
- const got = cache.get(a1);
- if (got !== undefined) {
- const ts = new Date().getTime();
- time = [[a1, ts], ...time.filter(([a, t]) => a !== a1)];
- cleanup();
- return got;
- }
- const val = func(a1);
- const ts = new Date().getTime();
- time = [[a1, ts], ...time];
- cache.set(a1, val);
- return val;
- };
- }
-
- const getCard = timedLRU1(async (uid) => {
- const json = await (await fetch(`https://api.bilibili.com/x/web-interface/card?mid=${uid}`, {
- // credentials: 'include',
- headers: {
- Accept: 'application/json',
- },
- method: 'GET',
- mode: 'cors',
- })).json();
- if (json.code === 0) {
- return json.data;
- }
- else {
- throw json.message;
- }
- });
- const getFansCount = async (uid) => {
- return (await getCard(uid)).card.fans;
- };
- const getSexTag = async (uid) => {
- const sex = (await getCard(uid)).card.sex;
- switch (sex) {
- case '男':
- return '♂';
- case '女':
- return '♀';
- default:
- return '〼';
- }
- };
- const getInfoByRoom = timedLRU1(async (roomid) => {
- const json = await (await fetch(`https://api.live.bilibili.com/xlive/web-room/v1/index/getInfoByRoom?room_id=${roomid}`, {
- // credentials: 'include',
- headers: {
- Accept: 'application/json',
- },
- method: 'GET',
- mode: 'cors',
- })).json();
- if (json.code === 0) {
- return json.data;
- }
- else {
- throw json.message;
- }
- });
- const getRoomFollowers = async (roomid) => {
- return (await getInfoByRoom(roomid)).anchor_info.relation_info.attention;
- };
- const followersTextClass = (followers) => {
- if (followers > 1e6) {
- return [`${Math.round(followers / 1e5) / 10}m★`, 'followers-m'];
- }
- else if (followers > 1e3) {
- return [`${Math.round(followers / 1e2) / 10}k★`, 'followers-k'];
- }
- else {
- return [`${followers}★`, ''];
- }
- };
-
- const parentNode$2 = $(`#area-tag-list`);
- const selector$2 = `a.Item_1EohdhbR`;
- GM_addStyle(`
- .processed::after {
- content: attr(data-followers);
- color: white;
- }
- .processed.followers-m::before{
- color: purple;
- }
- .processed.followers-k::before{
- color: red;
- }
- `);
- function 分区添加粉丝数 () {
- launchObserver({
- parentNode: parentNode$2,
- selector: selector$2,
- successCallback: () => {
- for (const a of $$(`a.Item_1EohdhbR`)) {
- (async () => {
- const nametag = a.querySelector(`.Item_QAOnosoB`);
- if (nametag.classList.contains('processed')) {
- return;
- }
- const followers = await getRoomFollowers(a.pathname.slice(1));
- let [txt, cls] = followersTextClass(followers);
- nametag.dataset.followers = txt;
- nametag.classList.add('processed');
- nametag.classList.add(cls);
- })();
- }
- },
- stopWhenSuccess: false,
- });
- }
-
- function 分区 () {
- 关注栏尺寸();
- 分区标题();
- 分区添加粉丝数();
- }
-
- function liveStatus() {
- switch ($`.live-status`.innerText) {
- case '直播':
- return '▶️'
- case '闲置':
- return '⏹️'
- case '轮播':
- return '🔁'
- default:
- return `【${$`.live-status`.innerText}】`
- }
- }
-
- const liveTitle = () => $`.live-title`.innerText;
- const liveHost = () => $`.room-owner-username`.innerText;
- const makeTitle = () => `${liveStatus()} ${liveTitle()} - ${liveHost()} - 哔哩哔哩直播`;
- const parentNode$1 = $`#head-info-vm .left-header-area`;
- const selector$1 = `.live-title`;
-
- function 直播间标题 () {
- launchObserver({
- parentNode: parentNode$1,
- selector: selector$1,
- successCallback: () => {
- document.title = makeTitle();
- },
- stopWhenSuccess: false,
- });
-
- document.title = makeTitle();
- }
-
- function 通用表情框尺寸修复 () {
- GM_addStyle(`
- #control-panel-ctnr-box > .border-box.top-left[style^="transform-origin: 249px "],
- #control-panel-ctnr-box > .border-box.top-left[style^="transform-origin: 251px "]
- {
- height: 700px
- }
- `);
- }
-
- const parentNode = $(`#chat-items`);
- const selector = `.user-name`;
- GM_addStyle(`.infoline::before{
- content: attr(data-infoline);
- color: white;
- }
- .infoline.followers-m::before{
- color: purple;
- }
- .infoline.followers-k::before{
- color: red;
- }
- `);
- const append = async (un) => {
- un.classList.add('infoline');
- const uid = un.parentNode.dataset.uid;
- const fans = await getFansCount(uid);
- const [txt, cls] = followersTextClass(fans);
- const sextag = await getSexTag(uid);
- un.dataset.infoline = `${sextag} ${txt} `;
- un.classList.add(cls);
- };
- function 直播间留言者显示粉丝数 () {
- launchObserver({
- parentNode,
- selector,
- successCallback: () => {
- for (const un of $$(`#chat-items .user-name`)) {
- if (un.classList.contains('infoline')) {
- continue;
- }
- append(un);
- }
- },
- stopWhenSuccess: false,
- });
- }
-
- function 动态井号标签 () {
- launchObserver({
- parentNode: document.body,
- selector: `a.dynamic-link-hover-bg`,
- successCallback: () => {
- for (let link of $$(`a.dynamic-link-hover-bg`)) {
- // link: HTMLAnchorElement
- if (/#.+#/.exec(link.innerHTML) && /https?:\/\/search.bilibili.com\/all\?.+/.exec(link.href)) {
- link.href = `https://t.bilibili.com/topic/name/${/#(.+)#/.exec(link.innerHTML)[1]}/feed`;
- }
- }
- },
- stopWhenSuccess: false,
- });
- }
-
- function 直播间 () {
- 关注栏尺寸();
- 直播间标题();
- 直播间留言者显示粉丝数();
- 通用表情框尺寸修复();
- 动态井号标签();
- }
-
- function 直播主页 () {
- 关注栏尺寸();
- }
-
- function 其他页面 () {
- 动态井号标签();
- }
-
- if (location.pathname === '/') {
- 直播主页();
- } else if (location.pathname === '/p/eden/area-tags') {
- 分区();
- } else if (/^\/\d+$/.exec(location.pathname)) {
- 直播间();
- } else {
- 其他页面();
- }
-
- })();