您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Make AV number, not BV code. F**k you BiliBili
当前为
// ==UserScript== // @name Make AV number, not BV code // @name:en Make AV number, not BV code // @name:zh-CN 要AV号,不要BV码 // @namespace https://pilipili.com/bv10492 // @version 0.1.2 // @description Make AV number, not BV code. F**k you BiliBili // @description:en Make AV number, not BV code. F**k you BiliBili // @description:zh-CN 要AV号,不要BV码,屑站飞了 // @author jk1551 // @require https://unpkg.com/[email protected]/dist/ajaxhook.min.js // @nocompat Chrome // @nocompat Firefox // @nocompat Opera // @nocompat Edge // @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://greasyfork.org/zh-CN/scripts/398526-give-me-av-not-bv (() => { if (typeof BigInt !== "function") { console.warn("Your browser does not support BigInt. AV/BV conversion is disabled."); return; } 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]] = BigInt(i); } const s = [11, 10, 3, 8, 4, 6]; const xor = BigInt(177451812); const add = BigInt(8728348608); const pow58 = []; // 58进制下2^32的最大位数(=6),也就是在此之前变动的最多位数,也就是s表的长度 const highestDigit = 6; for (let i = 0; i < highestDigit; i += 1) { pow58.push(BigInt(Math.pow(58, i))); } /** * @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 = BigInt(0); for (let i = 0; i < highestDigit; i += 1) { r += tr[x[s[i]]] * pow58[i]; } return Number((r - add) ^ xor); } /** * @param x {number} Exsiting AV number */ function enc(x) { x = BigInt(x); x = (x ^ xor) + add; const r = list("BV1 4 1 7 "); for (let i = 0; i < highestDigit; i += 1) { const index = (x / pow58[i]) % BigInt(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[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)/; 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[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)/; 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); } }); })();