Greasy Fork

Greasy Fork is available in English.

自用bilibili脚本

吧啦吧啦

当前为 2022-08-04 提交的版本,查看 最新版本

// ==UserScript==
// @name         自用bilibili脚本
// @namespace    mimiko/bilibili
// @version      0.0.11
// @description  吧啦吧啦
// @author       Mimiko
// @license      MIT
// @match        *://*.bilibili.com/*
// @grant        GM.addStyle
// grant        GM.registerMenuCommand
// grant        GM.xmlHttpRequest
// ==/UserScript==
// http://greasyfork.icu/zh-CN/scripts/436748-%E8%87%AA%E7%94%A8bilibili%E8%84%9A%E6%9C%AC
(() => {
  // 阻止脚本在iframe中被执行
  if (window.top !== window.self) return;
  // variable
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore
  const Monkey = GM;
  const cache = new Map();
  // const config = new Set()
  // const state = new Map()
  // function
  // 主站/番剧
  const asBangumiMain = () => {
    asPlayerMain();
    hideEl("#review_module"); // 隐藏点评
    Monkey.addStyle(".bpx-player-container { box-shadow: none !important; }");
  };
  // 主站/通用
  const asCommonMain = () => {
    Monkey.addStyle("body { overflow-x: hidden; }"); // 隐藏横向滚动条
    hideEl("#internationalHeader .nav-link-item:last-of-type"); // 移除下载APP
  };
  // 直播/首页
  const asIndexLive = async () => {
    // 隐藏顶部播放器
    hideEl(".player-area-ctnr");
    await getEl("video");
    removeEl(".player-area-ctnr");
  };
  // 主站/首页
  const asIndexMain = async () => {
    hideEl(
      ".contact-help",
      "#reportFirst2",
      "#reportFirst3",
      "#bili_live",
      "#bili_guochuang",
      "#bili_manga"
    );
    // 处理电梯
    await getEl("#elevator .item.sortable");
    Monkey.addStyle(
      [
        "#elevator { opacity: 0.1; transition: opacity 0.3s; }",
        "#elevator:hover { opacity: 1; }",
      ].join("\n")
    );
    hideElByText("#elevator .item.sortable", "直播");
    hideElByText("#elevator .item.sortable", "国创");
    hideElByText("#elevator .item.sortable", "漫画");
  };
  // 直播/入口
  const asLive = () => {
    const path = window.location.pathname;
    if (path === "/") return asIndexLive();
    if (parseInt(path.substring(1), 10)) return asRoomLive();
    return undefined;
  };
  // 主站/入口
  const asMain = () => {
    asCommonMain();
    const path = window.location.pathname;
    if (path === "/") return asIndexMain();
    if (path.startsWith("/video/BV")) return asVideoMain();
    if (path.startsWith("/bangumi/play/")) return asBangumiMain();
    return undefined;
  };
  // 主站/播放器
  const asPlayerMain = async () => {
    hideEl(
      ".bilibili-player-electric-panel",
      ".bilibili-player-ending-panel",
      ".bilibili-player-video-hint"
    );
    await turnWide();
    await focusPlayer();
  };
  // 直播/房间
  const asRoomLive = () => {
    removeEl("#my-dear-haruna-vm"); // 移除22/33娘
    hideEl("#room-background-vm"); // 隐藏背景
  };
  // 主站/视频
  const asVideoMain = () => {
    asPlayerMain();
    hideEl(".bilibili-player-video-popup-vote", ".bilibili-player-score");
    Monkey.addStyle(".bilibili-player { box-shadow: none !important; }");
  };
  // const checkIsLogin = () => {
  //   state.set('isLogin', !document.querySelector('.unlogin-avatar'))
  // }
  // 聚焦至播放器
  const focusPlayer = async () => {
    const $video = await getEl("video", "bwp-video");
    window.scrollTo({
      // left: document.documentElement.scrollLeft,
      top:
        document.documentElement.scrollTop +
        $video.getBoundingClientRect().top -
        10,
    });
  };
  // const get = async <T>(url: string): Promise<T> => {
  //   // @ts-ignore
  //   const { response } = await (GM as _GM).xmlHttpRequest({
  //     method: 'GET',
  //     url,
  //   })
  //   const { code, data, message } = JSON.parse(response)
  //   if (code) throw new Error(message)
  //   return data as T
  // }
  // 等待元素出现
  const getEl = (...listSelector) =>
    new Promise((resolve) => {
      const fn = () =>
        listSelector.some((selector) => {
          if (document.hidden) return false;
          const $el = document.querySelector(selector);
          if (!$el) return false;
          window.clearInterval(timer);
          resolve($el);
          return true;
        });
      const timer = window.setInterval(fn, 50);
      fn();
    });
  // 隐藏元素
  const hideEl = (...listSelector) =>
    Monkey.addStyle(
      listSelector
        .map((selector) => `${selector} { display: none !important; }`)
        .join("\n")
    );
  // 隐藏包含指定文本的元素
  const hideElByText = (selector, text) => {
    const $listNode = Array.from(document.querySelectorAll(selector)).filter(
      ($it) => $it.textContent?.trim() === text
    );
    $listNode.forEach(($it) => ($it.style.display = "none"));
  };
  // 菜单
  // const initMenu = () => {
  //   Monkey.registerMenuCommand('test', () => {
  //     alert('!')
  //   })
  // }
  // const log = <T>(
  //   message: T,
  // ): T => {
  //   console.log(message)
  //   return message
  // }
  // 入口
  const main = () => {
    // checkIsLogin()
    // initMenu()
    route();
    watch();
  };
  // 移除元素
  const removeEl = (selector) =>
    document.querySelectorAll(selector).forEach(($it) => $it.remove());
  // 路由
  const route = () => {
    const host = window.location.host.split(".")[0];
    if (host === "www") return asMain();
    if (host === "live") return asLive();
    return undefined;
  };
  // 挂起
  const sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));
  // 转为宽屏
  const turnWide = async () => {
    if (document.body.classList.contains("player-mode-widescreen")) return; // check
    const $btn = await getEl(
      ".bilibili-player-video-btn-widescreen",
      ".squirtle-video-widescreen"
    );
    $btn.click();
    if (document.body.classList.contains("player-mode-widescreen")) return; // re-check
    await sleep(100);
    await turnWide(); // loop
  };
  // 监听路由
  const watch = () => {
    cache.set("location", window.location.href);
    window.setInterval(() => {
      if (window.location.href === cache.get("location")) return;
      cache.set("location", window.location.href);
      route();
    }, 1e3);
  };
  // execute
  main();
})();