跳转到内容

MediaWiki:Gadget-abusefilter33test.js

来自萌娘共享
AnnAngela-dbot留言 | 贡献2025年7月24日 (四) 20:47的版本 (代码变动:103d1a56 - feat: rename (#594) by U:AnnAngela, co-authored-by: GH:github-actions[bot])

注意:在发布之后,您可能需要清除浏览器缓存才能看到所作出的更改的影响。

  • Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5Ctrl-R(Mac为⌘-R
  • Google Chrome:Ctrl-Shift-R(Mac为⌘-Shift-R
  • Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5
/**
 * -------------------------------------------------------------------------
 * !!! DON'T MODIFY THIS PAGE MANUALLY, YOUR CHANGES WILL BE OVERWRITTEN !!!
 * -------------------------------------------------------------------------
 */
var _addText = '{{GHIACode|page=GHIA:MoegirlPediaInterfaceCodes/blob/master/src/gadgets/abusefilter33test/Gadget-abusefilter33test.js|user=[[U:AnnAngela]]|co-authors=GH:github-actions[bot]|longId=103d1a563ea4ccc8ff29fb55c9bcd88329a56eb5|shortId=103d1a56|summary=feat: rename (#594)|body=<nowiki>Co-authored-by: github-actions[bot] <41898282+github-actions[bot]📧users.noreply.github.com></nowiki>}}'; 

/* <pre> */

"use strict";
$(() => (async () => {
    if (!mw.config.get("wgUserGroups").includes("sysop") && !mw.config.get("wgUserGroups").includes("staff")) {
        return;
    }
    if (mw.config.get("wgCanonicalSpecialPageName") !== "AbuseLog") {
        return;
    }
    const getLogVar = (varName) => $(`.mw-abuselog-details-${varName} .mw-abuselog-var-value .mw-abuselog-var-value`).text();
    const timestampVar = getLogVar("timestamp");
    const userName = getLogVar("user_name");
    const articlePrefixedtext = getLogVar("article_prefixedtext");
    const filter = [...document.querySelectorAll('a[href*="/Special:%E6%BB%A5%E7%94%A8%E8%BF%87%E6%BB%A4%E5%99%A8/"]')].filter(({ href }) => /%E6%BB%A5%E7%94%A8%E8%BF%87%E6%BB%A4%E5%99%A8\/[1-9]\d*$/.test(href))?.[0]?.href?.match?.(/[1-9]\d*$/)?.[0];
    if (timestampVar.length === 0 || userName.length === 0 || articlePrefixedtext.length === 0 || typeof filter !== "string") {
        return;
    }
    const symbolEnter = (str) => typeof str === "string" ? str.replace(/\n/g, "↵") : str;
    const api = new mw.Api();
    const pTable = $("<table/>");
    $("#mw-content-text > fieldset > p:first").after(pTable.css("width", "100%").addClass("wikitable"));
    pTable.empty().append("<tbody><tr><td style=\"text-align: center;\">加载中(<span id=\"abusefiltertest-progress\">0</span>/2)……</td></tr></tbody>");
    const progress = $("#abusefiltertest-progress");
    try {
        const __details = (await api.post({
            action: "query",
            assertuser: mw.config.get("wgUserName"),
            list: "abuselog",
            afluser: userName,
            afltitle: articlePrefixedtext,
            aflprop: "details",
            aflfilter: +filter,
        })).query.abuselog;
        if (__details.length === 0) {
            throw "无法找到对应用户名和页面标题的滥用过滤器日志";
        }
        progress.text(1);
        const _details = Array.from(new Map(__details.filter(({ details: { timestamp } }) => timestampVar === timestamp).map((n) => [n.new_wikitext, n])).values());
        if (_details.length === 0) {
            console.info(__details);
            throw "无法找到对应时间戳的滥用过滤器日志";
        }
        progress.text(2);
        const _rules = (await api.post({
            action: "query",
            assertuser: mw.config.get("wgUserName"),
            list: "abusefilters",
            abfstartid: +filter,
            abfendid: +filter,
            abfprop: "pattern",
        })).query.abusefilters[0].pattern.replace(/\r/g, "");
        const _stringRules = Array.from(_rules.match(/\/\* string rule start \*\/[\s\S]+?(?=\/\* string rule end \*\/)/g) || []).map((r) => r.replace(/\/\* regex rule start \*\//g, "").split("\n")).flat().map((r) => r.replace(/^ *"?/, "").replace(/"?,? *$/, "")).filter((r) => r !== "");
        const stringRules = new Set(_stringRules);
        const _regexRules = Array.from(_rules.match(/\/\* regex rule start \*\/[\s\S]+?(?=\/\* regex rule end \*\/)/g) || []).map((r) => r.replace(/\/\* regex rule start \*\//g, "").split("\n") || []).flat().map((r) => r.replace(/^ *"?/, "").replace(/"?,? *$/, "")).filter((r) => r !== "");
        const regexRules = new Set(_regexRules);
        if (stringRules.size + regexRules.size === 0) {
            throw "无法找到符合格式的规则";
        }
        for (const { details } of _details) {
            const addedLines = details.added_lines || details.new_wikitext;
            const result = [];
            const table = $("<table/>").css("width", "100%").addClass("wikitable abusefiltertest").hide();
            pTable.after(table);
            for (const sr of stringRules.values()) {
                if (addedLines.includes(sr)) {
                    const splits = addedLines.split(sr);
                    splits.forEach((str, i) => {
                        if (i === splits.length - 1) {
                            return;
                        }
                        const next = splits[i + 1];
                        const start = Math.max(0, str.length - 20);
                        const end = Math.min(next.length, 20);
                        result.push({
                            isRegexp: false,
                            rule: sr,
                            before: str.substring(start, start + 20),
                            string: sr,
                            after: next.substring(0, end),
                            start,
                        });
                    });
                }
            }
            for (const rr of regexRules.values()) {
                const regex = RegExp(`.{0,20}${rr}.{0,20}`, "ig");
                const findstring = RegExp(rr, "ig");
                if (regex.test(addedLines)) {
                    const splits = addedLines.match(regex);
                    let lastFromIndex = 0;
                    splits.forEach((str) => {
                        const string = str.match(findstring)[0];
                        const split = str.split(string);
                        const before = split[0];
                        const after = split.slice(1).join(string);
                        const start = addedLines.indexOf(string, lastFromIndex);
                        lastFromIndex = start + string.length;
                        result.push({
                            isRegex: true,
                            rule: rr,
                            before,
                            string,
                            after,
                            start,
                        });
                    });
                }
            }
            table.empty();
            if (result.length > 0) {
                table.append(`<caption style="font-weight: 700;">命中防滥用过滤器${filter}的内容</caption><tr><th style="text-align: right;">规则(请勿泄漏!!!)</th><th style="text-align: left;">命中字符串上下文</th></tr>`);
                result.sort(({ start: a }, { start: b }) => a - b);
                const results = [];
                result.forEach((r) => {
                    if (results.filter(({ isRegex, start }) => isRegex === r.isRegex && start === r.start).length === 0) {
                        results.push(r);
                    }
                });
                console.info(results);
                results.forEach(({ isRegex, rule, before, string, after, start }) => {
                    const tr = $("<tr/>");
                    const label = $("<td/>");
                    const ruleCode = $("<code/>");
                    ruleCode.text(rule);
                    label.addClass("mw-label");
                    label.text(isRegex ? "正则表达式" : "字符串");
                    label.append(symbolEnter(ruleCode)).append(":");
                    tr.append(label);
                    const input = $("<td/>");
                    input.addClass("mw-input");
                    const beforeSpan = $("<span/>");
                    beforeSpan.text(symbolEnter(before)).css({
                        padding: "0 .25em",
                    });
                    const strSpan = $("<span/>");
                    strSpan.text(symbolEnter(string)).css({
                        "font-weight": "700",
                        "text-decoration": "underline",
                        padding: "0 .25em",
                    });
                    const afterSpan = $("<span/>");
                    afterSpan.text(symbolEnter(after)).css({
                        padding: "0 .25em",
                    });
                    if (before.length >= 20) {
                        const beforeDot = $("<span/>");
                        beforeDot.text(`[${start}] ……`).css({
                            "padding-right": ".25em",
                        });
                        input.append(beforeDot);
                    }
                    input.append(beforeSpan).append(strSpan).append(afterSpan);
                    if (after.length >= 20) {
                        const afterDot = $("<span/>");
                        afterDot.text("……").css({
                            "padding-left": ".25em",
                        });
                        input.append(afterDot);
                    }
                    tr.append(input);
                    table.append(tr);
                });
            }
            else {
                table.empty().append("<tbody><tr><td style=\"text-align: center;\">现有规则没有匹配项……</td></tr></tbody>");
            }
        }
        pTable.hide();
        $(".abusefiltertest").show();
    }
    catch (e) {
        console.info("abusefiltertest", e);
        $(".abusefiltertest").remove();
        pTable.empty();
        if (filter === 33) {
            pTable.append(`<tbody><tr><td style="text-align: ${typeof e === "string" ? "center" : "left"};">发生错误:${typeof e === "string" ? e : `${e} ${e.stack.split("\n")[1].trim()}`}</td></tr></tbody>`);
        }
    }
})()); 

/* </pre> */