Greasy Fork

Greasy Fork is available in English.

Bilibili 账号已注销修正

修正Bilibili 账户已注销的主页链接,修改为 https://www.bilibili.com/list/$UID

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Bilibili 账号已注销修正
// @name:zh-CN   Bilibili 账号已注销修正
// @namespace    http://tampermonkey.net/
// @version      2.8.1.post
// @license      MIT
// @description  修正Bilibili 账户已注销的主页链接,修改为 https://www.bilibili.com/list/$UID
// @description:zh-CN  修正Bilibili 账户已注销的主页链接,修改为 https://www.bilibili.com/list/$UID
// @author       Kaesinol
// @match        https://*.bilibili.com/*
// @grant        GM.notification
// @grant        GM.openInTab
// @grant        GM.getValue
// @grant        GM.setValue
// @run-at       document-end
// @icon         https://www.gstatic.com/android/keyboard/emojikitchen/20220506/u1f47b/u1f47b_u1f5d1-ufe0f.png
// ==/UserScript==
async function showBetaInviteOnce() {
  const KEY = 'biliFix_beta_invited_v3';

  try {
    if (window.top !== window) return;
  } catch {
    return;
  }

  if (await GM.getValue(KEY)) return;

  await GM.setValue(KEY, true);

  GM.notification({
    title: '内测邀请',
    text: '嗨,目前3.0beta版已经发布,我们诚邀你进行这个版本的内测。',
    timeout: 8000,
    image: 'https://www.gstatic.com/android/keyboard/emojikitchen/20220506/u1f47b/u1f47b_u1f5d1-ufe0f.png',
    onclick: () => {
      GM.openInTab(
        'https://github.com/kaixinol/bilibili-account-deletion-correction/releases',
        { active: true }
      );
    }
  });
}

(async () => {
  await showBetaInviteOnce();
})();
(function () {
    "use strict";
    window.addEventListener(
        "biliFix:request-api",
        (e) => typeof e.detail === "function" && e.detail({ uidToShortId }),
    );

    const DEAD_USERNAME = "账号已注销";
    function estimateRegisterTime(uid) { // 来源: https://www.bilibili.com/read/cv35787158
        const n = BigInt(uid);
        const len = uid.length;
        if (len === 15 || len === 16) {
            return "≈ 2022-03-21 之后(15/16位UID时代)";
        }
        if (len === 10) return "≈ 2020-10-29 之后(10位UID时代)";

        const ranges = [
            [1n, 15n, "2009-06-24"],
            [16n, 20n, "2009-06-25"],
            [21n, 23n, "暂无资料"],
            [24n, 25n, "2009-06-26"],
            [26n, 26n, "2009-06-28"],
            [27n, 27n, "2009-06-29"],
            [28n, 29n, "2009-07-06"],
            [30n, 83n, "2009-07-09"],
            [84n, 84n, "2009-07-11"],
            [85n, 91n, "2009-07-12"],
            [92n, 528n, "2009-07-13"],
            [529n, 1543n, "2009-07-14"],
            [1544n, 5697n, "2009-07-15 ~ 2009-12-13"],
            [5698n, 5707n, "2009-12-14"],
            [5708n, 5711n, "2009-12-15"],
            [5712n, 5714n, "2009-12-16"],
            [5715n, 9999n, "2010-01-01 ~ 2010-02-05"],
            [10000n, 44186n, "2010-02-05 ~ 2010-06-25"],
            [44187n, 78765n, "2010-06-26 ~ 2010-12-23"],
            [78766n, 99999n, "2011-01-03 ~ 2011-02-03"],
            [100001n, 259332n, "2011-02-03 ~ 2011-12-16"],
            [259333n, 680417n, "2012-01-01 ~ 2012-12-26"],
            [680418n, 960021n, "2013-01-01 ~ 2013-05-02"],
            [1111111n, 2954623n, "2013-05-02 ~ 2013-12-31"],
            [2954624n, 7532842n, "2014-01-01 ~ 2014-12-31"],
            [7532843n, 9999999n, "2015-01-01 ~ 2015-05-01"],
            [10000000n, 20593642n, "2015-05-01 ~ 2015-12-31"],
            [20593643n, 73886290n, "2016-01-01 ~ 2016-12-31"],
            [73886291n, 99999999n, "2017-01-01 ~ 2017-03-31"],
            [100000000n, 272960616n, "2017-03-31 ~ 2017-12-31"],
            [272960617n, 393942207n, "2018-01-01 ~ 2018-12-31"],
            [393942208n, 490696435n, "2019-01-01 ~ 2019-12-31"],
            [490696436n, 703223216n, "2020-01-01 ~ 2020-10-29"],
        ];

        for (const [min, max, date] of ranges) {
            if (n >= min && n <= max) return date;
        }

        return "未知时间";
    }
    function processLinks() {
        const rules = {
            "space.bilibili.com/\\d+/favlist": {
                query: "div.bili-video-card__subtitle a",
            },
            "space.bilibili.com/\\d+/relation/*": {
                query: "a.relation-card-info__uname",
            },
            "www.bilibili.com/(video|list)/": {
                type: "intercept",
                query: [
                    ".up-detail-top a",
                    "a.staff-name",
                    "div.basic-desc-info a.mention-user",
                ],
            },
            "search.bilibili.com": {
                query: ".bili-video-card__info--owner",
            },
            "www.bilibili.com/opus/\\d+": {
                type: "override",
                query: ".opus-module-author:not([data-processed])",
            },
        };

        Object.entries(rules).forEach(([host, { query, type }]) => {
            if (RegExp(host).test(location.href)) {
                const queries = Array.isArray(query) ? query : [query];
                queries.forEach((q) => {
                    document.querySelectorAll(q).forEach((el) => {
                        handleElement(el, type);
                    });
                });
            }
        });
    }

    function uidToShortId(n) {
        n = BigInt(n);
        const chars =
            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
        let res = "";
        while (n > 0n) {
            res = chars[Number(n % 64n)] + res;
            n /= 64n;
        }
        return res || "A";
    }

    function handleElement(tag, type = "normal") {
        let text = null;
        let regular = true;

        if (
            ["space.bilibili.com", "search.bilibili.com", "bilibili.com/opus"]
                .some(
                    (prefix) =>
                        (location.hostname + location.pathname).includes(
                            prefix,
                        ),
                )
        ) {
            text = tag.text.split(" ").filter((s) => s.trim() !== "")[0];
            regular = false;
        } else {
            text = tag.text;
        }

        const str = text.trim();

        if (str === DEAD_USERNAME || str === `@${DEAD_USERNAME}`) {
            const match = type === "override"
                ? true
                : tag.href.match(/\/(\d+)\??/);

            tag.style.fontStyle = "italic";

            // ===== override(动态获取 uid)=====
            if (match && type === "override") {
                const uid = window.__INITIAL_STATE__?.detail?.basic?.uid ??
                    window.__INITIAL_STATE__?.detail?.modules?.find(
                        (m) => m.module_author,
                    )?.module_author?.mid;

                if (!uid) return;

                makeLinkPreview(tag, `https://www.bilibili.com/list/${uid}`);

                tag.addEventListener(
                    "click",
                    (e) => {
                        e.preventDefault();
                        window.open(
                            `https://www.bilibili.com/list/${uid}`,
                            "_blank",
                        );
                    },
                    { capture: true },
                );

                tag.querySelector(".opus-module-author__name").text = str +
                    uidToShortId(uid);

                tag.setAttribute("data-processed", "true");
                return;
            }

            // ===== 普通处理 =====
            if (match) {
                if (regular) {
                    tag.text = tag.text.trim() + uidToShortId(match[1]);
                } else {
                    tag.text = tag.text.replace(
                        str,
                        str + uidToShortId(match[1]),
                    );
                }
            }

            if (
                tag.scrollWidth > tag.clientWidth ||
                tag.scrollHeight > tag.clientHeight
            ) {
                tag.title = tag.textContent;
                if (tag.textContent.includes(" · ")) {
                    tag.textContent = tag.textContent.replace(
                        / · 收藏于\d+-\d+-\d+$/,
                        "",
                    );
                }
            }

            // ===== 跳转处理 =====
            if (match && type === "normal") {
                tag.href = `https://www.bilibili.com/list/${match[1]}`;
            } else if (match && type === "intercept") {
                makeLinkPreview(
                    tag,
                    `https://www.bilibili.com/list/${match[1]}`,
                );
            }
            const time = estimateRegisterTime(match[1]);

            if (!tag.dataset.regTimeAdded) {
                tag.setAttribute("data-reg-time", time);

                tag.title = tag.title
                    ? tag.title + "\n注册时间推测: " + time
                    : "注册时间推测: " + time;

                tag.dataset.regTimeAdded = "1";
            }
        }
    }

    function makeLinkPreview(el, url) {
        if (el.dataset.linkPreview === "1") return;
        el.dataset.linkPreview = "1";

        const proxy = document.createElement("span");

        Object.assign(proxy.style, {
            position: "absolute",
            top: "0",
            left: "0",
            width: "100%",
            height: "100%",
            display: "block",
            cursor: "pointer",
            zIndex: "10",
        });

        if (getComputedStyle(el).position === "static") {
            el.style.position = "relative";
        }

        proxy.addEventListener("click", (e) => {
            e.preventDefault();
            e.stopPropagation();
            window.open(url, "_blank", "noopener,noreferrer");
        });

        el.appendChild(proxy);
    }

    function processCommentRenderers(elements) {
        elements.forEach((renderer) => {
            const bili = renderer.shadowRoot.querySelector(
                "bili-comment-renderer",
            );
            const userInfo = bili.shadowRoot.querySelector(
                "bili-comment-user-info",
            );
            const user = userInfo.shadowRoot.querySelector("#user-name a");

            if (user) handleElement(user);

            function processRichTextLinks(richText) {
                richText.shadowRoot
                    .querySelector("bili-rich-text")
                    .shadowRoot.querySelectorAll('a[data-type="mention"]')
                    .forEach((a) => {
                        if (a.textContent.trim() === "@账号已注销") {
                            handleElement(a);
                        }
                    });
            }

            processRichTextLinks(bili);

            const replies = renderer.shadowRoot.querySelector(
                "bili-comment-replies-renderer",
            );

            const replyNodes = replies.shadowRoot.querySelectorAll(
                "bili-comment-reply-renderer",
            );

            replyNodes.forEach((reply) => {
                const rUser = reply.shadowRoot
                    .querySelector("bili-comment-user-info")
                    .shadowRoot.querySelector("#user-name a");

                if (rUser) handleElement(rUser);

                processRichTextLinks(reply);
            });

            if (!replies.shadowRoot.textContent.trim()) {
                renderer.setAttribute("data-processed", "true");
                return;
            }
        });
    }

    function processComments() {
        const startElement = document.querySelector("bili-comments");
        if (startElement && startElement.shadowRoot) {
            const allElements = startElement.shadowRoot.querySelectorAll(
                "bili-comment-thread-renderer:not([data-processed])",
            );
            processCommentRenderers(allElements);
        }
    }

    function tick() {
        processComments();
        processLinks();
    }

    // 初始执行 + 持续轮询
    tick();
    setInterval(tick, 2000);
})();