Greasy Fork

Greasy Fork is available in English.

自用bilibili脚本

吧啦吧啦

当前为 2023-05-06 提交的版本,查看 最新版本

// ==UserScript==
// @name         自用bilibili脚本
// @namespace    mimiko/bilibili
// @version      0.0.15
// @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
"use strict";
(() => {
  if (window.top !== window.self) return;
  // variable
  class Z {
    static getElements(selector) {
      return new Promise((resolve) => {
        const fn = () => {
          if (document.hidden) return;
          const $el = document.querySelectorAll(selector);
          if (!$el?.length) return;
          window.clearInterval(timer);
          resolve([...$el]);
        };
        const timer = window.setInterval(fn, 50);
        fn();
      });
    }
    static hideElements(...listSelector) {
      GM.addStyle(
        listSelector
          .map((selector) => `${selector} { display: none !important; }`)
          .join("\n")
      );
    }
    static load(name) {
      try {
        const data = localStorage.getItem(`mimiko-gms/${name}`);
        if (!data) return null;
        return JSON.parse(data);
      } catch (e) {
        alert(`读取缓存失败:${e.message}`);
        return null;
      }
    }
    static removeElements(selector) {
      document.querySelectorAll(selector).forEach(($it) => $it.remove());
    }
    static save(name, data) {
      localStorage.setItem(`mimiko-gms/${name}`, JSON.stringify(data));
    }
    static sleep(ts) {
      return new Promise((resolve) => setTimeout(resolve, ts));
    }
  }
  class Cache {
    list;
    constructor() {
      this.list = Z.load("cache-recommend") || [];
    }
    add(id) {
      const it = this.get(id);
      const it2 = [id, it[1] + 1];
      const list2 = this.list.filter((it) => it[0] !== id);
      list2.push(it2);
      this.list = list2.slice(-1e3);
    }
    clear() {
      this.list = [];
      this.save();
    }
    get(id) {
      return this.list.find((it) => it[0] === id) || [id, 0];
    }
    save() {
      Z.save("cache-recommend", this.list);
    }
  }
  const cache = new Cache();
  // function
  const asIndex = async () => {
    GM.addStyle(`
    body { min-width: auto; }
    @media (max-width: 1099.9px) {
      .recommend-container__2-line>*:nth-of-type(1n + 6) {
        display: block !important;
      }
    }
    .bili-video-card.is-rcmd.hidden .bili-video-card__wrap { opacity: 0.1; transition: opacity 0.3s; }
    .bili-video-card.is-rcmd.hidden:hover .bili-video-card__wrap { opacity: 1; }

    .bili-video-card.is-rcmd.hidden .reason-tip {
      position: absolute;
      width: 160px;
      height: 32px;
      left: 50%;
      top: 32%;
      text-align: center;
      line-height: 32px;
      background-color: rgba(0, 0, 0, 0.8);
      color: #fff;
      font-size: 12px;
      border-radius: 4px;
      pointer-events: none;
      transform: translate(-50%, -50%);
      transition: opacity 0.3s;
    }
    .bili-video-card.is-rcmd.hidden:hover .reason-tip { opacity: 0; }
    `);
    (await Z.getElements(".recommended-swipe"))[0].remove();
    // add cache clear button
    const containerButton = (await Z.getElements(".roll-btn-wrap"))[0];
    const btnClear = document.createElement("button");
    btnClear.classList.add("primary-btn", "roll-btn");
    btnClear.innerHTML = "<span>✖</span>";
    btnClear.setAttribute("title", "清空缓存");
    btnClear.addEventListener("click", () => {
      cache.clear();
      alert("缓存已清空");
    });
    btnClear.style.marginTop = "10px";
    containerButton.appendChild(btnClear);
    // check items
    const [container] = await Z.getElements(".recommend-container__2-line");
    const hide = async () => {
      observer.disconnect();
      const listItem = await Z.getElements(".bili-video-card.is-rcmd");
      listItem.forEach((it) => {
        const check = () => {
          const link = it.querySelector("a");
          if (!link) return "链接不存在";
          // has been viewed
          const id = link.href.replace(/.*\/BV/, "").replace(/\/\?.*/, "");
          if (cache.get(id)[1] > 1) return `已出现${cache.get(id)[1]}次`;
          cache.add(id);
          // info
          const info = it.querySelector(".bili-video-card__info--icon-text");
          if (info?.textContent === "已关注") return;
          // play count too low
          const stats = it.querySelector(".bili-video-card__stats");
          if (!stats) return "播放量不存在";
          const text = stats.textContent;
          if (!text) return "播放量为空";
          if (!text.includes("万")) return "播放量不足1万";
          const amount = parseFloat(text.split("万")[0]);
          if (amount < 3) return "播放量不足3万";
          return;
        };
        const reason = check();
        if (!reason) return;
        it.classList.add("hidden");
        const reasonTip = document.createElement("div");
        reasonTip.classList.add("reason-tip");
        reasonTip.textContent = reason;
        it.appendChild(reasonTip);
      });
      cache.save();
      listItem.sort((a, b) => {
        const aHidden = a.classList.contains("hidden");
        const bHidden = b.classList.contains("hidden");
        if (aHidden && !bHidden) return 1;
        if (!aHidden && bHidden) return -1;
        return 0;
      });
      listItem.forEach((it) => container.appendChild(it));
      observer.observe(container, {
        childList: true,
      });
    };
    const observer = new MutationObserver(hide);
    await hide();
  };
  const main = async () => {
    if (window.location.pathname === "/") await asIndex();
  };
  // execute
  main();
})();