User:Former User aDB0haVymg/gadgets/close-anx.js

维基百科,自由的百科全书

注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google ChromeFirefoxMicrosoft EdgeSafari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。

/**
 * <nowiki>
 *
 * Close-ANX.js
 * A simple gadget for Chinese Wikipedia
 *
 * ----
 *
 * Based on close-vip.js by User:Xiplus
 *
 * ----
 *
 * @author  User:Classy_Melissa @ zh.wikipedia.org
 * @license CC BY-SA (under protest)
 * @version 3
 * @since   2020-07-17
 *
 */
"use strict";
(function () {

    let ScriptConfig;
    if (typeof ScriptConfig == 'undefined')
        ScriptConfig = {};

    if (typeof ScriptConfig.summary == 'undefined') {
        ScriptConfig.summary = '關閉報告 via [[User:Classy_Melissa/gadgets/close-anx.js|close-anx]]';
    }

    // Melissa's Very Own Tunable Constants
    const POSSIBLE_PAGES = ["Wikipedia:管理员布告板/其他", "Wikipedia:管理员布告板/3RR"];

    // figure out targetPageTitle
    let targetPageTitle = "none";
    const currentPageTitle = mw.config.get("wgPageName");
    for (const thisPossiblePage of POSSIBLE_PAGES) {
        if (thisPossiblePage === currentPageTitle) {
            targetPageTitle = thisPossiblePage;
            break;
        }
    }

    // sanity check
    if (targetPageTitle === "none"
        || mw.config.get('wgAction') !== 'view'
        || mw.config.get('wgRevisionId') !== mw.config.get('wgCurRevisionId')) {
        return;
    }

    const fetchPageContentPromise = new Promise(function (resolve, reject) {
            new mw.Api().get({
                action: 'query',
                prop: 'revisions',
                rvprop: ['content', 'timestamp'],
                titles: targetPageTitle,
                formatversion: '2',
                curtimestamp: true
            }).then(function (data) {
                var page, revision;
                if (!data.query || !data.query.pages) {
                    mw.notify('未能抓取頁面內容(unknown)');
                    reject('unknown');
                }
                page = data.query.pages[0];
                if (!page || page.invalid) {
                    mw.notify('未能抓取頁面內容(invalidtitle)');
                    reject('invalidtitle');
                }
                if (page.missing) {
                    mw.notify('未能抓取頁面內容(nocreate-missing)');
                    reject('nocreate-missing');
                }
                revision = page.revisions[0];
                var content = revision.content;
                var basetimestamp = revision.timestamp;
                var curtimestamp = data.curtimestamp;
                resolve({
                    content: content,
                    basetimestamp: basetimestamp,
                    curtimestamp: curtimestamp
                });
            })
        }
    );

    /**
     * Shows the [close] buttons on each header
     */
    function showHeaderButtons() {
        const allContentH3s = document.querySelectorAll("#bodyContent h3");

        const getColouredSpan = function (color, content) {
            var span = document.createElement('span');
            span.style.color = color;
            span.appendChild(document.createTextNode(content));
            return span;
        };

        const buttonNodePrototype = document.createElement('strong');
        const closeLinkPrototype = document.createElement('a');
        closeLinkPrototype.appendChild(getColouredSpan('Black', '['));
        closeLinkPrototype.appendChild(getColouredSpan('Red', wgULS('关闭', '關閉')));
        closeLinkPrototype.appendChild(getColouredSpan('Black', ']'));
        buttonNodePrototype.setAttribute('class', 'CloseVipBtn');
        buttonNodePrototype.appendChild(closeLinkPrototype);

        allContentH3s.forEach(function (thisH3, thisKey) {

            const node = thisH3.getElementsByClassName('mw-headline')[0];
            const headlineChildren = $(thisH3).find('.mw-headline').children();
            if (headlineChildren.length === 0) {
                return;
            }

            let title = headlineChildren[0].id;
            title = title.replace(/{{vandal\|(.*?)}}/, '$1');

            const tmpNode = buttonNodePrototype.cloneNode(true);
            $(tmpNode.firstChild).click(function () {
                showCloseDialog(thisKey, title);
                return false;
            });

            node.appendChild(tmpNode);

        });
    }

    // ⚠ XSS Hot Spot
    function getHTMLTemplateCode() {

        let html = '<div>';

        // shorthand to append HTML
        const $ac = (str) => {
            html += str;
            html += "\n";
        };

        // shorthand to append warning option
        const $aw = (word) => {
            $ac(`<option value="{{警告}}: ${word}">警告: ${word}</option>"`);
        }

        // shorthand to append refuse option
        const $ar = (word) => {
            $ac(`<option value="{{VIP|dc}}: ${word}">拒絕: ${word}</option>`);
        }

        $ac('以{{VIP}}通告<br />');
        $ac('<select id="vip" onchange="$(this.parentElement).find(\'#comment\')[0].value += this.value; this.value = \'\';">');
        $ac('<option value="">選擇</option>');

        $ac('<option value="{{VIP|chk}}">檢查中</option>');
        $ac('<option value="{{VIP|m}}">將關注此用戶</option>');
        $ac('<option value="{{VIP|w}}">用戶已獲警告</option>');
        $ac('<option value="{{VIP|dc}}">拒絕</option>');
        $ac('<option value="{{VIP|n}}">注意</option>');
        $ac('<option value="{{VIP|e|X}}">陳舊報告,用戶已停止編輯/用戶近期已沒有編輯X</option>');
        $ac('<option value="{{VIP|q}}">問題</option>');

        $ar("請通過溝通解決爭議");
        $ar("未發出足夠警告");
        $ar("未違反任何方針");
        $aw("請勿再人身攻擊");
        $aw("請勿再發表不文明的言論");
        $aw("請勿再刪改他人留言");
        $aw("請勿再假定惡意");
        $aw("請勿再發表不實言論");

        $ac('</select><br />');
        $ac('{{Block}}<br />');
        $ac('<select id="block" onchange="$(this.parentElement).find(\'#comment\')[0].value += this.value; this.value = \'\';">');
        $ac('<option value="">選擇</option>');
        $ac('<option value="{{Blocked|1天}}">1天</option>');
        $ac('<option value="{{Blocked|1週}}">1週</option>');
        $ac('<option value="{{Blocked|1個月}}">1個月</option>');
        $ac('<option value="{{Blocked|1年}}">1年</option>');
        $ac('<option value="{{Blocked|indef}}">不限期封禁</option>');
        $ac('<option value="{{Blocked|ad=Example|1年}}">已由管理員Example執行封禁1年</option>');
        $ac('</select><br />');
        $ac('留言<br />');
        $ac('<input type="text" id="comment" size="40">');
        $ac('</div>');

        return html;

    }

    /**
     * Show a jQuery dialog to close a section.
     * @param key {number} the index of the section to close
     * @param title {string} the section's title. Supposed to be the username.
     */
    function showCloseDialog(key, title) {
        mw.loader.using(['jquery.ui'], function () {

            const dialogUIHTML = getHTMLTemplateCode();
            $(dialogUIHTML).dialog({
                title: '關閉報告 - ' + title,
                minWidth: 515,
                minHeight: 150,
                buttons: [
                    {
                        text: '確定',
                        click: function () {
                            if ($(this).find('#comment').val().trim() !== '') {
                                doCloseSection(key, title, $(this).find('#comment').val());
                            } else {
                                mw.notify('動作已取消');
                            }
                            $(this).dialog('close');
                        }
                    }, {
                        text: '取消',
                        click: function () {
                            $(this).dialog('close');
                        }
                    }
                ]
            });

        });
    }


    /**
     * Do close one section
     * @param key {number} the index of the section to close
     * @param title {string} the section's title
     * @param comment {string} comment to insert
     */
    function doCloseSection(key, title, comment) {
        new mw.Api().edit(targetPageTitle, function (revision) {

            const oldContent = revision.content;

            let contentSections = oldContent.split(/^===/gm);

            // remove the first section for now
            const firstSection = contentSections.shift();

            // add the ===s back to the strings
            contentSections = contentSections.map((section) => "===" + section);

            // do mutate contentSections as needed
            contentSections[key] = contentSections[key].trim();
            comment = comment.trim();
            if (comment !== '') {
                if (comment.search(/[.?!;。?!;]$/) === -1) {
                    comment += '。';
                }
                if (contentSections[key].match(/^\*\s*处理:[ \t]*(<!-- 非管理員僅可標記已執行的封禁,針對提報的意見請放在下一行 -->)?[ \t]*$/m)) {
                    contentSections[key] = contentSections[key].replace(/^(\*\s*处理:)[ \t]*(<!-- 非管理員僅可標記已執行的封禁,針對提報的意見請放在下一行 -->)?[ \t]*$/m, '$1' + comment + '--~~~~');

                } else {
                    contentSections[key] += '\n* 处理:' + comment + '--~~~~';
                }
            }
            contentSections[key] += '\n\n';
            let newContent = contentSections.join("");

            // re-insert the content of first section into newContent
            newContent = firstSection + newContent;

            // grey out the corresponding close button
            $($('#bodyContent').find('h3')[key - 1]).find('.CloseVipBtn span').css('color', 'grey');

            // done
            return {
                text: newContent,
                basetimestamp: revision.timestamp,
                summary: ScriptConfig.summary,
                minor: true
            };

        }).then(function () {
            mw.notify('已關閉 ' + title);
        }, function (e) {

            // handle errors from the API
            if (e === 'editconflict') {
                mw.notify('關閉 ' + title + ' 時發生編輯衝突');
            } else {
                mw.notify('關閉 ' + title + ' 時發生未知錯誤:' + e);
            }

        });
    }

    fetchPageContentPromise.then(function (result) {
        window.content = result.content;
        const lenintext = result.content.split(/^===/gm).length - 1;
        const leninhtml = $('#bodyContent').find('h3').length;
        if (leninhtml !== lenintext) {
            mw.notify('抓取章節錯誤,在HTML找到 ' + leninhtml + ' 個章節,在原始碼找到 ' + lenintext + ' 個章節');
        } else {
            showHeaderButtons();
        }
    });

})();
// </nowiki>