Greasy Fork

Greasy Fork is available in English.

修复B站评论区楼层

修复评论区评论的楼层号,包括视频、动态、专栏、话题、活动……

目前为 2021-04-09 提交的版本。查看 最新版本

// ==UserScript==
// @name         修复B站评论区楼层
// @namespace    MotooriKashin
// @version      0.0.7
// @description  修复评论区评论的楼层号,包括视频、动态、专栏、话题、活动……
// @author       MotooriKashin
// @match        *://*.bilibili.com/*
// @grant        none
// @license      MIT License
// ==/UserScript==

(function() {
    'use strict';

    let src, mode, type;

    const url = {
        reply : "https://api.bilibili.com/x/v2/reply",
        replymain : "https://api.bilibili.com/x/v2/reply/main",
        replycursor : "https://api.bilibili.com/x/v2/reply/reply/cursor",
        replydialog: "https://api.bilibili.com/x/v2/reply/dialog/cursor"
    }
    const xhr = (url) => {
        return new Promise((resolve, reject) => {
            let xhr = new XMLHttpRequest();
            xhr.open('get', url, true);
            xhr.withCredentials = true;
            xhr.onload = () => {
                if (xhr.status >= 200 && xhr.status < 300) resolve(xhr.response)
                else reject({status: xhr.status, statusText: xhr.statusText})
            };
            xhr.onerror = () => reject({status: xhr.status, statusText: xhr.statusText})
            xhr.send();
        });
    }
    const obj2search = (url, obj) =>{
        if (obj) {
            let arr = [],i = 0;
            for (let key in obj) {
                if(obj[key] !== "" && obj[key] !== "undefined" && obj[key] !== null) {
                    arr[i] = key + "=" + obj[key];
                    i++;
                }
            }
            url = url + "?" + arr.join("&");
        }
        return url;
    }
    const search2obj = (url) => {
            url = url.split('#')[0];
            url = url.split('?')[1] ? url.split('?')[1].split('&') : "";
            if (!url) return;
            let obj = {};
            for (let i = 0; i < url.length; i++) obj[url[i].split('=')[0]] = url[i].split('=')[1];
            return obj;
        }
    const setReplyFloor = async (link) => {
        src = "";
        try {
                let mode, data, obj = search2obj(link),
                    oid = obj.oid,
                    sort = obj.sort,
                    pn = obj.pn,
                    root = obj.root,
                    type = obj.type;
                if (sort == 0) mode = 1;
                if (sort == 1) return;
                if (sort == 2) mode = 3;
                let list_item = document.getElementsByClassName("reply-wrap");
                let main_floor = document.getElementsByTagName("li");
                if (root) {
                    if (pn < 2) data = await xhr(obj2search(url.replycursor, {"oid": oid,"root": root,"type": type}));
                    else {
                        let dialog;
                        if (list_item[0]) {
                            for (let i = 0; i < list_item.length; i++) {
                                if (list_item[i].getAttribute("data-id") == root) {
                                    list_item = list_item[i].getElementsByClassName("reply-wrap");
                                    if (list_item[0]) {
                                        for (let j = 0; j < list_item.length; j++) {
                                            if (!list_item[j].getElementsByClassName("floor")[0]) {
                                                dialog = list_item[j].getAttribute("data-id");
                                                break;
                                            }
                                        }
                                    }
                                    break;
                                }
                            }
                        }
                        else if (main_floor[0]) {
                            for (let i = 0; i < main_floor.length; i++) {
                                if (main_floor[i].getAttribute("id") && main_floor[i].getAttribute("id").includes(root)) {
                                    main_floor = main_floor[i].getElementsByTagName("li");
                                    if (main_floor[0]) {
                                        for (let j = 0; j < main_floor.length; j++) {
                                            if (main_floor[j].id && main_floor[j].id.includes("l_id") && !main_floor[j].getElementsByClassName("floor-num")[0]) {
                                                dialog = main_floor[j].getAttribute("id").split('_')[2];
                                                break;
                                            }
                                        }
                                    }
                                    break;
                                }
                            }
                        }
                        data = await xhr(obj2search(url.replydialog, {"oid": oid,"root": root,"type": type, "dialog": dialog, "size": 20}));
                        let min_id = JSON.parse(data).data.replies;
                        if (min_id) {
                            for (let i = 0; i < min_id.length; i++) {
                                if (min_id[i].rpid == dialog) {
                                    min_id = min_id[i].floor;
                                    break;
                                }
                            }
                        }
                        else return;
                        data = await xhr(obj2search(url.replycursor, {"oid": oid,"root": root,"type": type, "min_id": min_id}));
                    }
                }
                else {
                    if (sort == 2) data = await xhr(obj2search(url.replymain, {"oid": oid,"next": pn,"type": type,"mode": mode}));
                    else if (pn == 1) data = await xhr(obj2search(url.replymain, {"oid": oid,"type": type,"mode": mode}));
                    else {
                        pn = pn - 1;
                        data = await xhr(obj2search(url.reply, {"type": type,"sort": sort,"oid": oid,"pn": pn}));
                        data = JSON.parse(data).data;
                        let i = data.replies.length - 1;
                        oid = data.replies[0].oid;
                        let root = data.replies[i].rpid;
                        data = await xhr(obj2search(url.replycursor, {"oid": oid,"root": root,"type": type}));
                        data = JSON.parse(data).data;
                        oid = data.root.oid;
                        let next = data.root.floor;
                        data = await xhr(obj2search(url.replymain, {"oid": oid,"next": next,"type": type,"mode": mode}));
                    }
                }
            data = JSON.parse(data).data;
            let floor = {}, top = data.top, hots = data.hots, replies = data.replies, froot = data.root;
            if (hots && hots[0]) {
                for (let i = 0; i < hots.length; i++) {
                    floor[hots[i].rpid] = hots[i].floor;
                    if (hots[i].replies) {
                        for (let j = 0; j < hots[i].replies.length; j++) {
                            floor[hots[i].replies[j].rpid] = hots[i].replies[j].floor;
                        }
                    }
                }
            }
            if (replies && replies[0]) {
                for (let i = 0;i < replies.length; i++) {
                    floor[replies[i].rpid] = replies[i].floor;
                    if (replies[i].replies) {
                        for (let j = 0; j < replies[i].replies.length; j++) {
                            floor[replies[i].replies[j].rpid] = replies[i].replies[j].floor;
                        }
                    }
                }
            }
            if (top) {
                for (let key in top) {
                    if (top[key]) {
                        floor[top[key].rpid] = top[key].floor;
                        if (top[key].replies) {
                            for (let i = 0; i < top[key].replies.length; i++) {
                                floor[top[key].replies[i].rpid] = top[key].replies[i].floor;
                            }
                        }
                    }
                }
            }
            if (froot && froot.replies) for (let i = 0; i < froot.replies.length; i++) floor[froot.replies[i].rpid] = froot.replies[i].floor;
            if (main_floor[0]) {
                for (let i = 0; i < main_floor.length; i++) {
                    if (main_floor[i].id && main_floor[i].id.includes("l_id")) {
                        let rpid = main_floor[i].getAttribute("id").split('_')[2];
                        if (rpid in floor) {
                            try {
                                main_floor[i].getElementsByClassName("floor-num")[0].innerText = "#" + floor[rpid];
                            }
                            catch (e) {
                                let node = main_floor[i].getElementsByClassName("floor-date")[0].parentNode;
                                let span = document.createElement("span");
                                span.setAttribute("class", "floor-num");
                                span.setAttribute("style", "float: left;color: #aaa;padding-right: 10px;");
                                span.innerText = "#" + floor[rpid];
                                node.insertBefore(span,node.firstChild);
                            }
                        }
                    }
                }
            }
            if (list_item[0]) {
                for (let i = 0; i<list_item.length; i++) {
                    let rpid = list_item[i].getAttribute("data-id");
                    if (rpid in floor) {
                        let node = list_item[i].getElementsByClassName("info")[0];
                        let span = document.createElement("span");
                        span.setAttribute("class", "floor");
                        span.innerText = "#" + floor[rpid];
                        node.insertBefore(span,node.firstChild);
                    }
                }
            }
            }
            catch(e) {console.error(e)}
    }
    document.addEventListener("DOMNodeInserted",(msg) => {
        if (msg.target.src && msg.target.src.startsWith('https://api.bilibili.com/x/v2/reply') && msg.target.src.includes("oid")) src = msg.target.src;
        if (src && ((msg.target.id && /l_id/.test(msg.target.id)) || (msg.target.className && /reply-wrap/.test(msg.target.className)))) setReplyFloor(src);
    });
})();