B站之神赵怡宁

B站首页显示赵怡宁专区!

// ==UserScript==
// @name         B站之神赵怡宁
// @namespace    https://h7ml.cn
// @version      99.99.99
// @description  B站首页显示赵怡宁专区!
// @author       h7ml <h7ml@qq.com>
// @match        https://www.bilibili.com/*
// @icon         https://h7ml.cn/logo.png
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @license      MIT

// ==/UserScript==
;(function () {
  'use strict'
  GM_addStyle()

  const USERS = [
    {
      key_words: '赵怡宁',
      channel_id: 363612830,
      avatar:
        'https://i2.hdslb.com/bfs/face/8c4d71cdacb8a2cc111711d4b3ce6be8f060a0a0.jpg@240w_240h_1c_1s.webp',
    },
  ]

  let currentUserIndex = 0

  let currentPage = 1
  let page = 0
  let videoList = []

  const API = {
    getNewVideo: async () => {
      let res = await fetch(
        `https://api.bilibili.com/x/space/arc/search?mid=${USERS[currentUserIndex].channel_id}&ps=30&tid=0&pn=${currentPage}&order=pubdate&jsonp=jsonp`
      )
      const json = await res.json()
      videoList = videoList.concat(json.data.list.vlist)
    },
  }

  // 播放量格式化
  function bigNumber(num) {
    return num > 10000 ? `${(num / 10000).toFixed(2)}万` : num
  }

  function s2d(string) {
    return new DOMParser().parseFromString(string, 'text/html').body
      .childNodes[0]
  }
  // 播放时长格式化
  function timeFormat(time) {
    let res = []
    let h = 0
    let [s = 0, m = 0] = time.split(':').reverse()
    console.log(m, s)
    res.unshift(String(s).padStart(2, '0'))
    res.unshift(String(m % 60).padStart(2, '0'))
    res.unshift(String(parseInt(m / 60)).padStart(2, '0'))

    return res.join(':')
  }
  // 日期时间格式化
  function timeago(dateTimeStamp) {
    const minute = 60 //把分,时,天,周,半个月,一个月用毫秒表示
    const hour = minute * 60
    const day = hour * 24
    // const week = day * 7;
    const month = day * 30
    const now = parseInt(new Date().getTime() / 1000) //获取当前时间毫秒
    const diffValue = now - dateTimeStamp //时间差
    let result = ''
    if (diffValue < 0) {
      return
    }
    const minC = diffValue / minute //计算时间差的分,时,天,周,月
    const hourC = diffValue / hour
    const dayC = diffValue / day
    const monthC = diffValue / month
    const datetime = new Date()
    datetime.setTime(dateTimeStamp * 1000)
    const Nyear = datetime.getFullYear()
    const Nmonth = datetime.getMonth() + 1
    const Ndate = datetime.getDate()
    if (dayC >= 1 && dayC < 2) {
      result = '昨天'
    } else if (hourC >= 1 && hourC <= 23) {
      result = ' ' + parseInt(hourC) + '小时前'
    } else if (minC >= 1 && minC <= 59) {
      result = ' ' + parseInt(minC) + '分钟前'
    } else if (diffValue >= 0 && diffValue <= minute) {
      result = '刚刚'
    } else if (monthC < 12) {
      result = Nmonth + '-' + Ndate
    } else {
      result = Nyear + '-' + Nmonth + '-' + Ndate
    }
    return result
  }
  // 换一换
  async function refresh() {
    page++
    if (videoList.length <= page * 10 + 10) {
      await API.getNewVideo()
    }
    drawVideos()
  }

  function drawVideos() {
    const VIDEO_DOM = document.querySelector('#bili_custom .variety-body')
    VIDEO_DOM.innerHTML = ''

    videoList.slice(page * 10, page * 10 + 10).forEach((item) => {
      const title = item.title.replace(/<em class="keyword">(.*?)<\/em>/g, '$1')
      const pic = item.pic.replace(/http/g, 'https') + '@640w_400h_1c.webp'
      let DOM = s2d(`
        <div class="bili-video-card" data-report="partition_recommend.content">
  <div class="bili-video-card__skeleton hide">
    <div class="bili-video-card__skeleton--cover"></div>
    <div class="bili-video-card__skeleton--info">
      <div class="bili-video-card__skeleton--right">
        <p class="bili-video-card__skeleton--text"></p>
        <p class="bili-video-card__skeleton--text short"></p>
        <p class="bili-video-card__skeleton--light"></p>
      </div>
    </div>
  </div>
  <div class="bili-video-card__wrap __scale-wrap"><a href="//www.bilibili.com/video/${
    item.bvid
  }" target="_blank"
      data-mod="partition_recommend" data-idx="content" data-ext="click">
      <div class="bili-video-card__image __scale-player-wrap">
        <div class="bili-video-card__image--wrap">
          <div class="bili-watch-later" style="display: none;"><svg class="bili-watch-later__icon">
              <use xlink:href="#widget-watch-later"></use>
            </svg><span class="bili-watch-later__tip" style="display: none;"></span></div>
          <picture class="v-img bili-video-card__cover">
            <!---->
            <source srcset="${pic}"
              type="image/webp"><img
              src="${pic}"
              alt="${title}" loading="lazy" onload="">
          </picture>
          <div class="v-inline-player"></div>
        </div>
        <div class="bili-video-card__mask">
          <div class="bili-video-card__stats">
            <div class="bili-video-card__stats--left"><span class="bili-video-card__stats--item"><svg
                  class="bili-video-card__stats--icon">
                  <use xlink:href="#widget-video-play-count"></use>
                </svg><span class="bili-video-card__stats--text">${bigNumber(
                  item.play
                )}</span></span><span
                class="bili-video-card__stats--item"><svg class="bili-video-card__stats--icon">
                  <use xlink:href="#widget-video-danmaku"></use>
                </svg><span class="bili-video-card__stats--text">${
                  item.comment
                }</span></span></div><span
              class="bili-video-card__stats__duration">${timeFormat(
                item.length
              )}</span>
          </div>
        </div>
      </div>
    </a>
    <div class="bili-video-card__info __scale-disable">
      <div class="bili-video-card__info--right">
        <h3 class="bili-video-card__info--tit" title="${title}"><a href="//www.bilibili.com/video/${
        item.bvid
      }"
            target="_blank" data-mod="partition_recommend" data-idx="content" data-ext="click">${title}</a></h3>
        <div class="bili-video-card__info--bottom">
          <a class="bili-video-card__info--owner" href="//space.bilibili.com/${
            item.mid
          }" target="_blank"
            data-mod="partition_recommend" data-idx="content" data-ext="click"><svg
              class="bili-video-card__info--owner__up">
              <use xlink:href="#widget-up"></use>
            </svg><span class="bili-video-card__info--author">${
              item.author
            }</span><span
            class="bili-video-card__info--date">· ${timeago(
              item.created
            )}</span></a>
        </div>
      </div>
    </div>
  </div>
</div>
`)
      VIDEO_DOM.append(DOM)
    })
  }

  async function injectDOM(e) {
    currentUserIndex = e ? e.target.getAttribute('index') : 0
    videoList = []
    currentPage = 1
    page = 0

    const DOM = `
    <div id="bili_custom">
    <section class="bili-grid">
  <div class="variety-area">
    <div class="area-header">
      <div class="left"><a id="${USERS[currentUserIndex].key_words}" class="the-world area-anchor" data-id="6"></a>
        <img src="${USERS[currentUserIndex].avatar}" style="width: 34px; height: 34px; border-radius: 17px; margin-right: 12px;">
        <a class="title" href="https://space.bilibili.com/${USERS[currentUserIndex].channel_id}/video"
          target="_blank"><span>${USERS[currentUserIndex].key_words}</span></a></div>
      <div class="right"><button class="primary-btn roll-btn custom-refresh"><svg style="transform: rotate(0deg);">
            <use xlink:href="#widget-roll"></use>
          </svg><span>换一换</span></button><a class="primary-btn see-more" href="https://space.bilibili.com/${USERS[currentUserIndex].channel_id}/video"
          target="_blank"><span>查看更多</span><svg>
            <use xlink:href="#widget-arrow"></use>
          </svg></a></div>
    </div>
    <div class="variety-body"></div>
    </div>
  </section>
</div>`
    let content = document.querySelector('.bili-layout')
    let anchor = document.querySelectorAll('.bili-grid')[2]
    let init = s2d(DOM)
    document.querySelector('#bili_custom') &&
      document.querySelector('#bili_custom').remove()
    // 插入初始模版
    content.insertBefore(init, anchor)

    // 插入最新视频
    await API.getNewVideo()
    drawVideos()
    // 点击事件
    document.querySelector('.custom-refresh').addEventListener('click', refresh)
  }

  window.addEventListener(
    'load',
    async () => {
      await injectDOM()
      console.log('加载赵怡宁-bilibili插件')
    },
    false
  )
})()