我不喜欢 IP 属地,但是你手机都显示了,为什么电脑不显示呢?目前仅视频、动态评论区
当前为
// ==UserScript==
// @name 哔哩哔哩网页版展示 IP 属地
// @namespace http://zhangmaimai.com
// @version 1.5.7
// @author MaxChang3
// @description 我不喜欢 IP 属地,但是你手机都显示了,为什么电脑不显示呢?目前仅视频、动态评论区
// @license MIT
// @icon https://www.bilibili.com/favicon.ico
// @match https://www.bilibili.com/video/*
// @match https://www.bilibili.com/list/*
// @match https://www.bilibili.com/bangumi/play/*
// @match https://t.bilibili.com/*
// @match https://www.bilibili.com/opus/*
// @match https://space.bilibili.com/*
// @match https://www.bilibili.com/v/topic/detail/*
// @match https://www.bilibili.com/cheese/play/*
// @match https://www.bilibili.com/festival/*
// @grant unsafeWindow
// @run-at document-body
// ==/UserScript==
(function () {
'use strict';
const isElementLoaded = async (selector, root = document) => {
const getElement = () => root.querySelector(selector);
return new Promise((resolve) => {
const element = getElement();
if (element)
return resolve(element);
const observer = new MutationObserver((_) => {
const element2 = getElement();
if (!element2)
return;
resolve(element2);
observer.disconnect();
});
observer.observe(root === document ? root.body : root, {
childList: true,
subtree: true
});
});
};
const startsWithAny = (str, prefixes) => prefixes.some((prefix) => str.startsWith(prefix));
const getLocationFromElement = (replyItemEl) => {
var _a;
const userInfoEl = replyItemEl.className.startsWith("sub") ? replyItemEl.querySelector(".sub-user-name") : replyItemEl.querySelector(".user-name");
const userInfo = userInfoEl ? userInfoEl.textContent ?? "" : "";
const locationString = ((_a = userInfo.match(/\[(.*?)\]/)) == null ? void 0 : _a[1]) ?? "IP属地:未知";
if (userInfoEl)
userInfoEl.innerHTML = userInfoEl.innerHTML.replace(/\[(.*?)\]/, "");
return ` ${locationString}`;
};
const insertLocation = (replyItemEl) => {
const replyInfo = replyItemEl.className.startsWith("sub") ? replyItemEl.querySelector(".sub-reply-info") : replyItemEl.querySelector(".reply-info");
if (!replyInfo)
throw Error("Can not detect reply info");
replyInfo.children[0].innerHTML += getLocationFromElement(replyItemEl);
};
const isReplyItem = (el) => el instanceof HTMLDivElement && ["reply-item", "sub-reply-item"].includes(el.className);
const observeAndInjectComments = async (root) => {
const targetNode = await isElementLoaded(".reply-list", root);
const observer = new MutationObserver((mutationsList) => {
for (let mutation of mutationsList) {
if (mutation.type !== "childList")
continue;
mutation.addedNodes.forEach((node) => {
if (!isReplyItem(node))
return;
insertLocation(node);
if (node.className.startsWith("sub"))
return;
const subReplyListEl = node.querySelector(".sub-reply-list");
if (!subReplyListEl)
return;
const subReplyList = Array.from(subReplyListEl.children);
subReplyList.pop();
subReplyList.map(insertLocation);
});
}
});
observer.observe(targetNode, { childList: true, subtree: true });
};
const serveNewComments = async (itemSelector, root = document) => {
const dynList = await isElementLoaded(itemSelector, root);
let lastObserved;
const observer = new MutationObserver((mutationsList) => {
for (let mutation of mutationsList) {
if (mutation.type !== "childList" || !(mutation.target instanceof HTMLElement) || !mutation.target.classList.contains("bili-comment-container") || mutation.target === lastObserved)
continue;
observeAndInjectComments(mutation.target);
lastObserved = mutation.target;
}
});
observer.observe(dynList, { childList: true, subtree: true });
};
var _unsafeWindow = /* @__PURE__ */ (() => typeof unsafeWindow != "undefined" ? unsafeWindow : void 0)();
const getLocationString = (replyItem) => {
var _a;
const locationString = (_a = replyItem == null ? void 0 : replyItem.reply_control) == null ? void 0 : _a.location;
return locationString ?? "IP属地:未知";
};
const injectLocation = (reply) => {
var _a;
reply.member.uname = `${reply.member.uname}[${getLocationString(reply)}]`;
(_a = reply.replies) == null ? void 0 : _a.forEach(injectLocation);
};
const hookNext = () => {
const fetchInterceptor = {
apply: async function(target, thisArg, argumentsList) {
const [url] = argumentsList;
if (url.startsWith("//api.bilibili.com/x/v2/reply/wbi") || url.startsWith("//api.bilibili.com/x/v2/reply/reply")) {
const res = await Reflect.apply(target, thisArg, argumentsList);
const hackedRes = res.clone();
hackedRes.json = async () => {
var _a, _b, _c;
const json = await res.json();
json.data.replies.forEach(injectLocation);
if ((_b = (_a = json.data) == null ? void 0 : _a.top) == null ? void 0 : _b.upper)
injectLocation(json.data.top.upper);
if ((_c = json.data) == null ? void 0 : _c.top_replies)
json.data.top_replies.forEach(injectLocation);
return json;
};
return hackedRes;
}
return Reflect.apply(target, thisArg, argumentsList);
}
};
_unsafeWindow.fetch = new Proxy(fetch, fetchInterceptor);
};
const pageType = {
"dynamic": Symbol("dynamic"),
"bangumi": Symbol("bangumi")
};
const hookBbComment = async (type) => {
if (type === pageType.dynamic) {
const dynBtn = await isElementLoaded(".bili-dyn-action.comment");
if (dynBtn)
dynBtn.click();
await isElementLoaded(".bb-comment");
dynBtn.click();
} else if (type === pageType.bangumi) {
await isElementLoaded(".bb-comment");
}
const bbComment = _unsafeWindow.bbComment;
if (!bbComment)
throw Error("Can not detect bbComment");
const createListCon = bbComment.prototype._createListCon;
const createSubReplyItem = bbComment.prototype._createSubReplyItem;
const applyHandler = (target, thisArg, args) => {
const [item] = args;
const result = Reflect.apply(target, thisArg, args);
const replyTimeRegex = /<span class="reply-time">(.*?)<\/span>/;
return result.replace(replyTimeRegex, `<span class="reply-time">$1 ${getLocationString(item)}</span>`);
};
bbComment.prototype._createListCon = new Proxy(createListCon, { apply: applyHandler });
bbComment.prototype._createSubReplyItem = new Proxy(createSubReplyItem, { apply: applyHandler });
};
const matchPrefix = async (url) => {
var _a;
if (startsWithAny(url, [
"https://www.bilibili.com/video/",
// 视频
"https://www.bilibili.com/list/",
// 新列表
"https://www.bilibili.com/opus/",
// 新版单独动态页
"https://www.bilibili.com/cheese/play/"
// 课程页
])) {
hookNext();
observeAndInjectComments();
} else if (url.startsWith("https://www.bilibili.com/bangumi/play/")) {
const isNewBangumi = !!document.querySelector("meta[name=next-head-count]");
if (isNewBangumi) {
hookNext();
observeAndInjectComments();
} else {
hookBbComment(pageType.bangumi);
}
} else if (url.startsWith("https://www.bilibili.com/v/topic/detail/")) {
hookNext();
serveNewComments(".list-view");
} else if (url.startsWith("https://space.bilibili.com/") && url.endsWith("dynamic")) {
hookNext();
serveNewComments(".bili-dyn-list__items");
} else if (url.startsWith("https://space.bilibili.com/")) {
hookNext();
const dynamicTab = await isElementLoaded(".n-dynamic");
dynamicTab.addEventListener("click", () => {
serveNewComments(".bili-dyn-list__items");
}, { once: true });
} else if (url.startsWith("https://t.bilibili.com/") && location.pathname === "/") {
const dynHome = await isElementLoaded(".bili-dyn-home--member");
const isNewDyn = (_a = dynHome.querySelector(".bili-dyn-sidebar__btn")) == null ? void 0 : _a.innerText.startsWith("新版反馈");
if (isNewDyn) {
hookNext();
serveNewComments(".bili-dyn-list");
} else {
hookBbComment(pageType.dynamic);
}
} else if (url.startsWith("https://t.bilibili.com/")) {
const dynItem = await isElementLoaded(".bili-dyn-item");
const isNewDyn = !!dynItem.querySelector(".bili-comment-container");
if (isNewDyn) {
hookNext();
const commentContainer = await isElementLoaded(".bili-comment-container", dynItem);
observeAndInjectComments(commentContainer);
} else {
hookBbComment(pageType.dynamic);
}
} else if (url.startsWith("https://www.bilibili.com/festival/")) {
hookBbComment(pageType.bangumi);
}
};
matchPrefix(location.href);
})();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址