Greasy Fork

Greasy Fork is available in English.

枢-争议提醒

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

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

"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");