要AV号,不要BV码

Make AV number, not BV code. F**k you BiliBili

目前為 2020-03-23 提交的版本,檢視 最新版本

// ==UserScript==
// @name           要AV号,不要BV码
// @name:en        Make AV number, not BV code
// @namespace      https://pilipili.com/bv10492
// @version        0.1
// @description    Make AV number, not BV code. F**k you BiliBili
// @description:en Make AV number, not BV code. F**k you BiliBili
// @author         jk1551
// @require        https://unpkg.com/[email protected]/dist/ajaxhook.min.js
// @match          https://www.bilibili.com/video/*
// @match          http://www.bilibili.com/video/*
// @match          https://acg.tv/*
// @match          http://acg.tv/*
// @match          https://b23.tv/*
// @match          http://b23.tv/*
// @grant          none
// ==/UserScript==

/* jshint esversion: 6 */

const CONFIG = {
    autoJump: false
};

// GM代码构思来自 https://gf.qytechs.cn/zh-CN/scripts/398526-give-me-av-not-bv

const bv2av = (() => {
    // https://www.zhihu.com/question/381784377/answer/1099438784
    const table = "fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF";
    const tr = Object.create(null);

    for (let i = 0; i < 58; i += 1) {
        tr[table[i]] = i;
    }

    const s = [11, 10, 3, 8, 4, 6];
    const xor = 177451812;
    const add = 8728348608;

    /**
     * @param s {string}
     */
    function list(s) {
        return s.split("");
    }

    /**
     * @param x {string} BV string; including the beginning "BV" (e.g. "BV17x411w7KC")
     */
    function dec(x) {
        let r = 0;

        for (let i = 0; i < 6; i += 1) {
            r += tr[x[s[i]]] * Math.pow(58, i);
        }

        return (r - add) ^ xor;
    }

    /**
     * @param x {number} AV number
     */
    function enc(x) {
        x = (x ^ xor) + add;

        const r = list("BV1  4 1 7  ");

        for (let i = 0; i < 6; i += 1) {
            const index = Math.pow((x / 58) | 0, i % 58);
            r[s[i]] = table[index];
        }

        return r.join("");
    }

    return {
        enc: enc,
        dec: dec
    };
})();

/**
 * @param avNumber {number | string}
 */
function getAvUrl(avNumber) {
    return "//www.bilibili.com/video/av" + avNumber.toString();
}

/**
 * @param avNumber {number | string}
 */
function appendOrUpdateAvNumberLink(avNumber) {
    const avInfoLabels = document.getElementsByClassName("video-data");
    // 分区和日期
    const infoLabel1 = avInfoLabels[0];
    // 直接塞到和infoLabel1同级会导致谜之排版错误
    const info1 = infoLabel1.children[0];
    let link;

    if (info1.children.length === 2) {
        // 原始状态(只有分区和日期两个span)
        const span = document.createElement("span");
        link = document.createElement("a");
        link.textContent = "av" + avNumber.toString();
        link.href = getAvUrl(avNumber);
        info1.appendChild(span);
    } else if (info1.children.length > 2) {
        // pilipili的谜之DOM更新,又不像是VDOM
        // 本来添加了一个span和a,但是刷新之后反而变成了a是info1的第一个子元素
        link = info1.children[0];
        link.textContent = "av" + avNumber.toString();
        link.href = getAvUrl(avNumber);
        link.style.marginRight = "16px";
    }
}

(() => {
    const bvUrlRE = /www\.bilibili\.com\/video\/(BV[ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjklmnopqrstuvwxyz123456789]+)/;
    const bvmatch = bvUrlRE.exec(window.location.href);

    if (bvmatch) {
        console.log("F**k You BV Number!");

        if (CONFIG.autoJump) {
            const bvstr = bvmatch[1];
            const avNumber = bv2av.dec(bvstr);
            const url = getAvUrl(avNumber);
            window.location.href = url;
        }
    }
})();

let isContentRefreshed = false;
let isAvNumberWritten = false;
let avNumber = Number.NaN;

// TODO: 处理 HTML5 History 相关

const bvidRE = /bvid=(BV[ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjklmnopqrstuvwxyz123456789]+)/;
const aidRE = /aid=(\d+)/;

ah.proxy({
    //请求发起前进入
    onRequest: (config, handler) => {
        while (config.url.indexOf("api.bilibili.com/x/web-interface/view") > 0) {
            let match = bvidRE.exec(config.url);

            if (match) {
                // https://api.bilibili.com/x/web-interface/view?cid=167028524&bvid=BV1TE411A7VJ
                avNumber = bv2av.dec(match[1]);
                isContentRefreshed = true;
                break;
            }

            match = aidRE.exec(config.url);

            if (match) {
                // https://api.bilibili.com/x/web-interface/view?cid=167028524&aid=97836354
                avNumber = Number.parseInt(match[1]);
                isContentRefreshed = true;
                break;
            }

            break;
        }

        handler.next(config);
    },

    //请求成功后进入
    onResponse: (response, handler) => {
        if (isContentRefreshed) {
            if (isAvNumberWritten) {
                if (!Number.isNaN(avNumber)) {
                    setTimeout(() => {
                        appendOrUpdateAvNumberLink(avNumber);
                    });
                    isAvNumberWritten = true;
                }
            } else {
                if (!Number.isNaN(avNumber)) {
                    setTimeout(() => {
                        appendOrUpdateAvNumberLink(avNumber);
                    });
                }
            }
        }

        handler.next(response);
    }
});

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址