BiliBili User Custom Name

自定义bilibili用户名(仅本地生效)

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name        BiliBili User Custom Name
// @namespace   _s7util__
// @description 自定义bilibili用户名(仅本地生效)
// @match       https://space.bilibili.com/*
// @match       https://www.bilibili.com/*
// @match       https://search.bilibili.com/*
// @grant       none
// @version     1.0.0
// @author      shc0743
// @license     GPL-3.0
// @run-at      document-end
// @grant       GM_setValue
// @grant       GM_getValue
// @grant       GM_listValues
// @grant       GM_deleteValue
// ==/UserScript==

(async function () {

  // loader-mapping
  const mapping = {
    'https://space.bilibili.com/': fnPersonSpace,
    'https://www.bilibili.com/video/': fnVideoPage,
    'https://www.bilibili.com/blackboard/': fnNop,
    'https://www.bilibili.com/v/': fnNop,
    'https://www.bilibili.com/anime/': fnNop,
    'https://www.bilibili.com/match/': fnNop,
    'https://www.bilibili.com/': fnMainSite,
    'https://search.bilibili.com/': fnSearchSite,
  };
  // loader
  const url = location.href;
  let ret = 0;
  for (const i in mapping) {
    if (url.startsWith(i)) {
      ret = mapping[i].call(this, url);
      break;
    }
  }
  return ret;
  // loader end

  // utility start
  function getCustomName(name, def = ''){
    if (def === '') def = name
    return GM_getValue(name, def)
  }
  function setCustomName(name, value = null){
    if (!value) return GM_deleteValue(name)
    return GM_setValue(name, value)
  }
  // utility end


  function fnNop () {}
  function fnPersonSpace (){
    const m = createMutation();
    m.config(['.fans-name', '.idc-uname']);


    const el = document.getElementById('h-name');
    if (!el || !el.innerText) return setTimeout(fnPersonSpace, 1000)
    el.dataset.originalName = el.innerText
    el.addEventListener('dblclick', () => {
      const dlg = document.createElement('dialog')
      const inp = document.createElement('input')
      inp.value = el.innerText
      inp.setAttribute('style', 'padding: 10px; font-size: large; width: 400px; height: 1em;')
      inp.onblur = () => dlg.close();
      inp.onkeydown = (ev) => {
        if (ev.key === 'Escape') inp.value = ''
        if (ev.key === 'Enter') inp.blur()
      }
      dlg.onclose = () => {
        setCustomName(el.dataset.originalName, inp.value)
        el.innerText = inp.value || el.dataset.originalName
        dlg.remove()
      }
      dlg.append(inp)
      document.body.append(dlg)
      dlg.showModal()
    })
    el.innerText = getCustomName(el.dataset.originalName)
  }
  function fnVideoPage (){
    const m = createMutation()
    m.config(['.up-name']);

// TODO
  }
  function fnMainSite (){
    const m = createMutation()
    m.config(['.up-info-container .up-name', '.bili-video-card__info--author']);

// TODO
  }
  function fnSearchSite() {
    const m = createMutation()
    m.config(['.bili-video-card__info--author']);
    // TODO
  }

  function createMutation(el = document.documentElement) {
    // TODO: 处理shadow DOM树
    const config = {
      selectors: [],
    };
    let queued = false;
    function queueFn() {
      queued = false;
      o.disconnect();

      // main
      const allSelectors =config.selectors.join(',');
      const roots = [document] // 处理shadowDOM需递归,考虑将主体部分提到单独函数
      for (const root of roots) {
        const els = root.querySelectorAll(allSelectors);
        for (const el of els) {
          if (el && el.__bucn_count__ && el.__bucn_count__ > 10) continue;
          el.__bucn_count__ = (el.__bucn_count__ || 0) + 1;

          const n = getCustomName(el.innerText);
          if (n) el.innerText = n;
        }
      }

      o.observe(el, { attributes: true, childList: true, subtree: true });
    }
	  const o = new MutationObserver(function (mutationsList, observer) {
      //for (const i of mutationsList) {
        //const el = i.target;
        //if (el && el.__bucn_count__ && el.__bucn_count__ > 10) continue;
        //el.__bucn_count__ = (el.__bucn_count__ || 0) + 1;
      //}
      if (queued) return;
      queueMicrotask(queueFn)
      queued = true;
    });
    o.config = function (args) {
      for(const  i of args) {
        /*if (i.startsWith('#')) config.ids.push(i.substring(1));
        else if (i.startsWith('.')) config.ids.push(i.substring(1));*/
        config.selectors.push(i)
      }
    }
    o.observe(el, { attributes: true, childList: true, subtree: true });
	  return o;
  }

}())