您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
显示评论区IP属地
// ==UserScript== // @name b站显示评论区IP属地 // @version 1.1 // @description 显示评论区IP属地 // @author Akias // @license MIT // @match https://*.bilibili.com/* // @icon https://www.bilibili.com/favicon.ico // @grant unsafeWindow // @run-at document-start // @noframes // @namespace https://greasyfork.org/users/1094863 // ==/UserScript== const originalXHROpen = XMLHttpRequest.prototype.open XMLHttpRequest.prototype.open = function (...args) { originalXHROpen.apply(this, args) if (args[1] == '//api.bilibili.com/x/web-interface/nav') { this.addEventListener('readystatechange', function () { if (this.readyState == 4 && this.status == 200) { if (JSON.parse(this.response).code == 0) main() } }) XMLHttpRequest.prototype.open = originalXHROpen } } const ipMap = new Map() function main() { const originalFetch = fetch unsafeWindow.fetch = async function (...args) { let res = await originalFetch(...args) let url = args[0].split('?')[0] if (url == '//api.bilibili.com/x/v2/reply/wbi/main' || url == '//api.bilibili.com/x/v2/reply/reply') { for (let r of (await res.clone().json()).data.replies) { ipMap.set(r.member.mid, r.reply_control.location) for (let rr of r.replies) ipMap.set(rr.member.mid, rr.reply_control.location) } } return res } new MutationObserver(mutationsList => { for (let mutation of mutationsList) { let n = mutation.target if (n.nodeType == 1) { if (n.className == 'reply-list') { addReplyLocation(mutation.addedNodes[0], '') } else if (n.className == 'sub-reply-list') { addReplyLocation(mutation.addedNodes[0], 'sub-') } } } }).observe(document.body, { childList: true, subtree: true }) } function addReplyLocation(node, s) { if (node && node.className == `${s}reply-item`) { let location = ipMap.get(node.querySelector(`.${s}user-name`).getAttribute('data-user-id')) if (!location) return let rt = node.querySelector(`.${s}reply-time`) let rl = rt.cloneNode(false) rl.className = `${s}reply-location` rl.innerHTML = location rt.insertAdjacentElement('afterend', rl) if (!s) { for (let sr of node.getElementsByClassName('sub-reply-item')) { addReplyLocation(sr, 'sub-') } } } }