BiliBili User Custom Name

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

// ==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;
  }

}())