显示 AV/BV

在视频页显示 AV/BV 号

  1. // ==UserScript==
  2. // @name 显示 AV/BV
  3. // @namespace im.outv.userscript.bvav
  4. // @version 1.0
  5. // @description 在视频页显示 AV/BV 号
  6. // @author Outvi V
  7. // @match *://www.bilibili.com/*
  8. // @match *://bilibili.com/*
  9. // @license MIT
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. ;(function () {
  14. 'use strict'
  15.  
  16. const VBR_TRY_COUNT = 12
  17. const AV_SPAN_ID = '__bvav__span_av'
  18. const BV_SPAN_ID = '__bvav__span_bv'
  19.  
  20. const Log = (...args) => console.log('[bvav]', ...args)
  21.  
  22. function nowOrReady(cb) {
  23. if (document.readyState !== 'loading') {
  24. cb()
  25. } else {
  26. document.addEventListener('DOMContentLoaded', () => {
  27. cb()
  28. })
  29. }
  30. }
  31.  
  32. function sleep(ms) {
  33. return new Promise((r) => {
  34. setTimeout(() => {
  35. r()
  36. }, ms)
  37. })
  38. }
  39.  
  40. function findOrCreateAndUpdateText(id, value) {
  41. let elem = document.querySelector('#' + id)
  42. if (!elem) {
  43. elem = document.createElement('span')
  44. elem.id = id
  45. elem.classList.add('a-crumbs')
  46. const ih = document.querySelector('.video-data')
  47. ih.appendChild(elem)
  48. }
  49. elem.innerText = value
  50. }
  51.  
  52. function appendAvBv() {
  53. document
  54. .querySelector('.video-data')
  55. .lastElementChild.classList.add('a-crumbs')
  56. findOrCreateAndUpdateText(AV_SPAN_ID, 'av' + window.aid)
  57. findOrCreateAndUpdateText(BV_SPAN_ID, window.bvid)
  58. }
  59.  
  60. // Monitor on hydration
  61. function setupBodyObserver() {
  62. const body = document.body
  63. Log('Monitoring changes of #app')
  64. const observer = new MutationObserver((muts) => {
  65. muts.map((x) => {
  66. if (x.addedNodes) {
  67. const nodes = [...x.addedNodes].filter((y) => y.id === 'app')
  68. if (nodes.length > 0) {
  69. Log('#app has changed, re-observing')
  70. setupObserver(nodes[nodes.length - 1])
  71. }
  72. }
  73. })
  74. })
  75. observer.observe(body, {
  76. childList: true,
  77. })
  78. }
  79.  
  80. async function setupObserver(app) {
  81. let tries = 0
  82. let vbr = null
  83. while (vbr === null && tries < VBR_TRY_COUNT) {
  84. await sleep(800)
  85. vbr = app.querySelector('#viewbox_report')
  86. tries++
  87. if (tries > 0) Log('Still waiting for VBR')
  88. }
  89. if (tries > VBR_TRY_COUNT) {
  90. Log('Cannot find VBR, giving up')
  91. return
  92. }
  93.  
  94. appendAvBv()
  95.  
  96. const observer = new MutationObserver((muts) => {
  97. muts.map((x) => {
  98. if (x.target.tagName === 'H1') {
  99. appendAvBv()
  100. Log(x)
  101. }
  102. })
  103. })
  104.  
  105. observer.observe(vbr, {
  106. subtree: true,
  107. attributes: true,
  108. })
  109.  
  110. Log('Observing VBR:', vbr)
  111. }
  112.  
  113. nowOrReady(() => {
  114. Log('Setting up...')
  115. setupObserver(document.querySelector('#app'))
  116. setupBodyObserver()
  117. })
  118. })()

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址