Greasy Fork is available in English.

枢-争议提醒

创建一个开放、和谐的社区环境,让其他用户能够鉴别存在争议的用户!

"use strict";
// ==UserScript==
// @name         枢-争议提醒
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  创建一个开放、和谐的社区环境,让其他用户能够鉴别存在争议的用户!
// @author       枢 Devs
// @include      /https?://www\.bilibili\.com/video/.+/
// @include      /https?:\/\/space\.bilibili\.com\/\d+([/?].+)?/
// @icon         https://www.google.com/s2/favicons?domain=bilibili.com
// @grant        none
// @include      /https?://t\.bilibili\.com/.+/
// ==/UserScript==
var Mode;
(function (Mode) {
    Mode[Mode["QUERY"] = 0] = "QUERY";
    Mode[Mode["ALL"] = 1] = "ALL";
    Mode[Mode["OFFLINE"] = 2] = "OFFLINE";
})(Mode || (Mode = {}));
//设置
//API相关
const API = "https://api.fuckanti.com";
const API_QUERY = "/GetBadGuy";
const API_GET_ALL = "/GetBadGuys";
//模式相关
//QUERY=单次查询模式 效果最好
//ALL=仅获取获取一次模式 最节省服务器资源
//OFFLINE=离线模式 使用下方的OFFLINE_STATS列表
const QUERY_MODE = Mode.QUERY;
//离线模式列表
const OFFLINE_LIST = [
    {
        mid: 1,
        tag: "测试标签1",
        color: "#62ffff",
    },
    {
        mid: 2,
        tag: "测试标签2",
        color: "#ff6a00",
    }
];
//正则匹配表
const REG_VIDEO = /https?:\/\/www\.bilibili\.com\/video\/.+/;
const REG_READ = /https?:\/\/www\.bilibili\.com\/read\/.+/;
const REG_USER_SPACE = /https?:\/\/space\.bilibili\.com\/\d+([/?].+)?/;
const REG_DYNAMIC = /https?:\/\/space\.bilibili\.com\/\d+\/dynamic/;
const REG_DYNAMIC_SPECIFY = /https?:\/\/t\.bilibili\.com\/.+/;
class UStats {
    constructor() {
        this.mid = 0;
        this.tag = "";
        this.color = "";
    }
}
class UStatsOnline extends UStats {
    constructor() {
        super(...arguments);
        this.url = "";
        this.score = 0;
    }
}
class UStatsResponse {
    constructor() {
        this.ErrorCode = 0;
        this.Msg = "";
        this.Success = false;
        this.Data = [];
    }
}
let ALL_LIST = null;
function filtering(mid, lst) {
    let ret = [];
    if (mid instanceof Set) {
        lst.forEach(s => {
            mid.forEach(m => {
                if (s.mid === m)
                    ret.push(s);
            });
        });
    }
    else {
        lst.forEach(s => {
            if (s.mid == mid)
                ret.push(s);
        });
    }
    return ret;
}
function getStats(mid, callback) {
    if (mid instanceof Set && mid.size === 0)
        return;
    let ret = [];
    switch (QUERY_MODE) {
        case Mode.QUERY:
            let req = new XMLHttpRequest();
            req.open("GET", API + API_QUERY + "?mid=" + (mid instanceof Set ? Array.from(mid).toString() : mid));
            req.onload = _ => {
                let usr = JSON.parse(req.response);
                callback(usr.Data, usr);
            };
            req.send();
            break;
        case Mode.ALL:
            if (ALL_LIST === null) {
                let req = new XMLHttpRequest();
                req.open("GET", API + API_GET_ALL);
                req.onload = _ => {
                    let usr = JSON.parse(req.response);
                    ALL_LIST = usr.Data;
                    ret = filtering(mid, ALL_LIST);
                    callback(ret, null);
                };
                req.send();
            }
            else {
                ret = filtering(mid, ALL_LIST);
                callback(ret, null);
            }
            break;
        case Mode.OFFLINE:
            ret = filtering(mid, OFFLINE_LIST);
            callback(ret, null);
            break;
    }
}
function draw(u, s) {
    u.setAttribute("style", "color:" + s.color);
    let str = u.textContent;
    str = str + " | <" + s.tag + ">";
    if (s instanceof UStatsOnline) {
        str = str + " [" + s.score + "]";
        if (s.url !== "") {
            u.setAttribute("herf", s.url);
        }
    }
    u.textContent = str;
}
function drawComment(ue, us) {
    if (ue.length === 0 || us.length === 0)
        return;
    ue.forEach(u => {
        us.forEach(s => {
            try {
                if (Number(u.getAttribute("data-usercard-mid")) === s.mid) {
                    draw(u, s);
                }
            }
            catch (ignored) {
            }
        });
    });
}
function observe(observer, elem) {
    if (elem !== null) {
        observer.observe(elem, {
            childList: true,
            subtree: true,
            characterDataOldValue: true
        });
        console.log("开始监听");
    }
}
function drawUserSpace(us) {
    console.log("准备绘制个人空间");
    let obs = new MutationObserver(_ => {
        let elem = document.getElementById("h-name");
        if (elem !== null) {
            draw(elem, us);
            obs.disconnect();
        }
    });
    observe(obs, document.body);
}
function startObserve() {
    let observer = new MutationObserver(mutationRecords => {
        let mids = new Set();
        let elems = new Array();
        mutationRecords.forEach(rcd => {
            if (rcd.type == "childList") {
                try {
                    let users = Array.from(rcd.addedNodes);
                    users.forEach(user => {
                        try {
                            let lst = user.getElementsByTagName("a");
                            for (let i = 0; i < lst.length; ++i) {
                                try {
                                    let item = lst.item(i);
                                    if (item !== null && item.attributes[0].name === "data-usercard-mid") {
                                        let id = item.attributes[0].value;
                                        mids.add(Number(id));
                                        elems.push(item);
                                    }
                                }
                                catch (ignored) {
                                }
                            }
                        }
                        catch (ignored) {
                        }
                    });
                }
                catch (e) {
                    console.warn(e);
                }
            }
        });
        getStats(mids, (us, usr) => {
            if (usr !== null) {
                if (usr.Success && us.length > 0) {
                    drawComment(elems, us);
                }
                else {
                    console.warn(usr.Msg + "错误代码:" + usr.ErrorCode);
                }
            }
            else {
                if (us.length > 0) {
                    drawComment(elems, us);
                }
            }
        });
    });
    let elem = null;
    if (document.URL.match(REG_VIDEO)) {
        elem = document.getElementById("comment");
    }
    // else if (document.URL.match(REG_DYNAMIC)) {
    //     elem = document.getElementById("page-dynamic")
    // } else if (document.URL.match(REG_READ) || document.URL.match(REG_DYNAMIC_SPECIFY)) {
    //     elem = document.getElementById("app")
    // }
    observe(observer, elem);
}
class Injector {
    constructor() {
        this.help = () => {
            console.log(`帮助:
        help() => void: 帮助菜单
        [测试用]
        randColor() => string: 获取随机颜色
        randUStats() => UStats: 获取随机UStats
        randUStatsOnline() => UStatsOnline: 获取随机UStatsOnline
        testDrawElem(elem :Element,isOnline :boolean =false ) => void: 尝试绘制元素
        testDrawComment(count :number = 5,isOnline :boolean = false) => void: 尝试绘制指定个数评论(默认:5)
        testDrawUserSpace(isOnline :boolean = false) => void: 尝试绘制个人空间`.trim());
        };
        this.randColor = () => {
            return '#' + Math.floor(Math.random() * 0xFFFFFF).toString(16).padEnd(6, '0');
        };
        this.randUStats = () => {
            let us = new UStats();
            us.color = this.randColor();
            us.tag = "测试标签";
            return us;
        };
        this.randUStatsOnline = () => {
            let us = new UStatsOnline();
            us.color = this.randColor();
            us.tag = "测试标签";
            us.score = Math.floor(Math.random() * 101);
            return us;
        };
        this.testDrawElem = (elem, isOnline = false) => {
            let us = isOnline ? this.randUStatsOnline() : this.randUStats();
            if (elem.getAttribute("testdraw") === "true") {
                console.log("目标已绘制,仅变更颜色。");
                elem.setAttribute("style", "color:" + us.color);
            }
            else {
                elem.setAttribute("testdraw", "true");
                elem.setAttribute("style", "color:" + us.color);
                let str = elem.textContent;
                str = str + " | <" + us.tag + ">";
                console.log("us instanceof UStatsOnline:");
                if (us instanceof UStatsOnline) {
                    str = str + " [" + us.score + "]";
                }
                elem.textContent = str;
                console.log("测试绘制完毕。");
            }
        };
        this.testDrawUserSpace = (isOnline = false) => {
            let elem = document.getElementById("h-name");
            if (elem !== null) {
                this.testDrawElem(elem, isOnline);
            }
        };
        this.testDrawComment = (count = 5, isOnline = false) => {
            let users = document.getElementsByClassName("user");
            for (let idx = 0, draw = 0; idx < users.length && draw < count; ++idx) {
                let items = users[idx].getElementsByTagName("a");
                for (let i = 0; i < users.length; ++i) {
                    try {
                        let item = items.item(i);
                        if (item !== null && item.attributes[0].name === "data-usercard-mid") {
                            if (item.getAttribute("testdraw") == "true")
                                continue;
                            this.testDrawElem(item, isOnline);
                            ++draw;
                        }
                    }
                    catch (ignored) {
                    }
                }
            }
        };
        // @ts-ignore
        document.BiliMarker = this;
    }
}
function empty(s) {
    return (s === "" || s === null || s === undefined);
}
//脚本开始
//@ts-ignore
if (QUERY_MODE !== Mode.OFFLINE) {
    if (empty(API))
        throw "API must not be empty with online mode!";
    //@ts-ignore
    if (QUERY_MODE === Mode.QUERY && empty(API_QUERY))
        throw "Query API must not be empty with query mode!";
    //@ts-ignore
    if (QUERY_MODE === Mode.ALL && empty(API_GET_ALL))
        throw "Get all API must not be empty with get all mode!";
}
//注入
new Injector();
//个人空间匹配
if (document.URL.match(REG_USER_SPACE)) {
    const REG_USER_SPACE_UID = /^https?:\/\/space\.bilibili\.com\/(\d+)(?:.+)*?$/;
    try {
        let ret = document.URL.match(REG_USER_SPACE_UID);
        if (ret !== null && ret.length > 1) {
            let uid = Number(ret[1]);
            getStats(uid, (us, usr) => {
                us.forEach(u => {
                    console.log(u);
                });
                if (usr !== null) {
                    if (usr.Success) {
                        drawUserSpace(us[0]);
                    }
                    else {
                        console.warn(usr.Msg + "错误代码:" + usr.ErrorCode);
                    }
                }
                else if (us.length > 0 && uid === us[0].mid) {
                    drawUserSpace(us[0]);
                }
            });
        }
    }
    catch (e) {
        console.warn("个人空间绘制失败");
        console.warn(e);
    }
}
//开始观测
startObserve();
console.log("BiliMark: Work work.jpg");