bilibili显示直播信息

bilibili直播间显示开播时间和直播时长,粉丝数,分区等信息

目前為 2023-12-30 提交的版本,檢視 最新版本

/// ==UserScript==
// @name         bilibili显示直播信息
// @description  bilibili直播间显示开播时间和直播时长,粉丝数,分区等信息
// @version      1.0
// @author       wqz
// @match        https://live.bilibili.com/*
// @license      MIT
// @grant        none
// @namespace https://greasyfork.org/users/1060750
// ==/UserScript==

(function () {
  ("use strict");
  // @require      https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js

  let line1;            // 开播时间
  let line2;            // 直播持续时间
  let live_status;      // 直播状态  0:未开播 1:直播中 2:轮播中
  let liveStartTime;
  let roomId;
  let liveData;
  let text_areaName;
  let rightText;
  let showmore;
  let interval1;
  let interval5;


  // document.addEventListener('DOMContentLoaded', function () {
  $(document).ready(function () {
    window.addEventListener('load', function () {
      main();
    });

    async function main() {
      try {


        // 获取直播间id
        roomId = getRoomID()
        console.log(`roomId: ${roomId}`);

        // 异步获取直播信息
        liveData = await getLiveInfo(roomId);

        live_status = liveData.data.live_status
        console.log(liveData);

        // 初始化UI
        createOSD();
        initOSD()


        // 启动 setInterval,并保存返回的 ID
        interval1 = setInterval(() => updateOSD1(), 1000);
        interval5 = setInterval(() => updateOSD5(), 5000);
        updateOSD1();
        updateOSD5();

      } catch (error) {
        console.error("发生错误:", error);
        clearInterval(interval1);
        clearInterval(interval5);
      }
    }

    // 获取直播间id
    function getRoomID() {
      const urlpathname = window.location.pathname;
      console.log(`urlpathname: ${urlpathname}`);
      return urlpathname.match(/\d{3,}/)[0];
    }

    // 获取直播信息
    async function getLiveInfo(roomId) {
      const apiUrl = `https://api.live.bilibili.com/room/v1/Room/get_info?room_id=${roomId}`;
      try {
        const response = await fetch(apiUrl);
        if (!response.ok) {
          throw new Error(`请求错误: ${response.status}`);
        }
        const data = await response.json();
        if (data.code === 0) {
          return data;
        } else {
          throw new Error(`获取直播信息失败: ${data.message}`);
        }
      } catch (error) {
        throw new Error(`请求错误: ${error.message}`);
      }
    }


    // 初始化UI
    function initOSD() {
      // 开播时间
      liveStartTime = liveData.data.live_time
      console.log(`直播开始时间: ${liveStartTime}`);
      line1.textContent = `开播时间:${liveStartTime}`;

      const pan = liveData.data.parent_area_name
      const an = liveData.data.area_name
      text_areaName.textContent = '分区: ' + (pan ? pan + ' > ' + an : an)

    }

    // 创建UI
    function createOSD() {

      // 创建父 div
      const containerDiv = document.createElement("div");
      containerDiv.style.display = "flex";
      containerDiv.style.marginLeft = "10px"; // 设置左边距
      containerDiv.style.userSelect = "text";
      containerDiv.style.flexDirection = "column";
      containerDiv.classList.add('live-skin-normal-a-text')
      // 第一行文本
      line1 = document.createElement("div");
      line1.textContent = `开播时间:xxxxxxxx`;
      line1.style.opacity = 0.8; // 设置透明度
      containerDiv.appendChild(line1);
      // 第二行文本
      line2 = document.createElement("div");
      line2.textContent = "直播时长:x小时xx分钟xx秒";
      line2.style.opacity = 0.8; // 设置透明度
      containerDiv.appendChild(line2);
      const fatherElement = document.querySelector("#head-info-vm > div > div > div.upper-row > div.left-ctnr.left-header-area");
      fatherElement.appendChild(containerDiv);


      // 分区信息
      text_areaName = document.createElement('span')
      // text_areaName.classList.add('v-middle,ts-dot-4')
      text_areaName.textContent = '分区: 父分区 > 子分区'
      // text_areaName.style.marginLeft = '14px'
      text_areaName.style.fontSize = '14px';
      let f = document.querySelector("#sections-vm > div.section-block.f-clear.z-section-blocks > div.left-container > div.room-info-ctnr > ul")
      f.after(text_areaName)


      // 右边text
      rightText = document.createElement('div');
      rightText.textContent = '粉丝数:xx  人气值:xx'
      rightText.classList.add('live-skin-normal-a-text', 'v-middle', 'preserve-space')
      rightText.style.display = 'flex';
      rightText.style.justifyContent = 'flex-end';
      rightText.style.opacity = 0.8;
      rightText.style.marginBottom = "2px";

      let oldElement = document.querySelector("#head-info-vm > div > div > div.upper-row > div.right-ctnr")
      let newElement = document.createElement('div');
      newElement.appendChild(rightText);
      newElement.appendChild(oldElement.cloneNode(true));
      oldElement.parentNode.replaceChild(newElement, oldElement);

    }

    // 更新UI文本
    function updateOSD1() {
      const updateLiveTime = () => {
        const currentTime = new Date();
        const startTime = new Date(liveStartTime);
        const elapsedSeconds = Math.floor((currentTime - startTime) / 1000);
        const hours = Math.floor(elapsedSeconds / 3600);
        const minutes = Math.floor((elapsedSeconds % 3600) / 60);
        const seconds = elapsedSeconds % 60;
        // 格式化为时分秒的形式
        const formattedTime = `直播时长:${hours.toString()}小时
      ${minutes.toString().padStart(2, "0")}分钟
      ${seconds.toString().padStart(2, "0")}秒`;

        // 更新文本节点的内容
        line2.textContent = formattedTime;
      }
      updateLiveTime()
    }

    async function updateOSD5() {
      liveData = await getLiveInfo(roomId);
      const updatePopularity = () => {
        rightText.textContent = `粉丝数:${liveData.data.attention}  人气值:${liveData.data.online}`
      }
      updatePopularity()
    }

  })();
});