Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/** MIT Licensed - see https://github.com/Awesome-Aasim/WikiRCPatrol/blob/master/LICENSE* * Copyright (c) 2020-23 Awesome Aasim and contributors* * Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the "Software"), to deal* in the Software without restriction, including without limitation the rights* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:** The above copyright notice and this permission notice shall be included in all* copies or substantial portions of the Software.* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE* SOFTWARE.* This script is a work in progress.  Your help in developing this tool is welcomed at https://github.com/Awesome-Aasim/WikiRCPatrol.* Contributions and changes to this script should be made at the GitHub repository above.* All other changes will be lost if this file is rebuilt and saved.* By contributing to this project, you agree to release your work under the MIT license.*/mw.loader.using(['oojs-ui-core', 'oojs-ui.styles.icons-editing-core', 'oojs-ui.styles.icons-movement', 'oojs-ui.styles.icons-interactions', 'oojs-ui.styles.icons-layout', 'oojs-ui.styles.icons-alerts'], function () {    if (!window.rcpatrol) { // stops multiple instances of RC patrol from running        //necessary resources        var rcpatrol = {};        window.rcpatrol = rcpatrol;        if (mw.config.get("wgPageName").toLowerCase() == "Special:RecentChanges".toLowerCase()) {            rcpatrol = true;            $(document).ready(function () {                var rcpatrollocation = mw.config.get("wgArticlePath").replace("$1", "Special:BlankPage/RCPatrol")                $("#mw-content-text").prepend('<a href="' + rcpatrollocation + '">RC patrol</a> (<a href="' + rcpatrollocation + '?oresreview=1">ORES</a>)');            });        }        if ((mw.config.get("wgPageName").toLowerCase() == "Special:BlankPage/RCPatrol".toLowerCase())) {            /**             * Initialize variables related to RC patrol             */            rcpatrol.changes = [];            rcpatrol.currentChange = 0;            window.setInterval(() => {                $("#rcpatroldiff").find("a").attr("target", "_blank");                $(".mw-rollback-link").hide();                $(".ve-init-mw-diffPage-diffMode").hide();                $(".mw-revslider-container").hide();                if (rcpatrol.currentChange == 0) {                    rcpatrol.previouseditbutton.setDisabled(true);                } else if (!rcpatrol.isDisabled) {                    rcpatrol.previouseditbutton.setDisabled(false);                }            }, 100);            $(document).ready(function () {                rcpatrol.fetch();                $("#firstHeading, #section_0").html("Recent Changes Patrol");                $("title").text("Recent Changes Patrol - " + mw.config.get("wgSiteName"));                /*                if (mw.config.get("skin") == "minerva") {                    $("body").html($("main").html());                    $("#siteNotice").prepend('<a id="rcpatrolexit" href="/">Exit</a>');                    $("#rcpatrolexit").click(function () {                        window.history.back();                    })                }                */                $("#mw-content-text").html("");                $("#mw-content-text").append('<div id="rcpatrolbuttons"></div>');                $("#mw-content-text").append('<div id="rcpatroldiff"></div>');                $("#rcpatrolbuttons").prepend(rcpatrol.rcpatrolbar.$element);                $("#rcpatrolbuttons").prepend(rcpatrol.rollbackbar.$element);                $("#rcpatrolbuttons").prepend(rcpatrol.dropdownmenu.$element);                $("#rcpatrolbuttons").prepend('<a href="https://www.how.com.vn/wiki/en/Special:BlankPage/RCPatrol?oresreview=1">Only show edits that likely need review</a><br>');                if (mw.config.get('wgUserGroups').includes('sysop')) {                    $("#rcpatrolbuttons").append('<div>Admin tools: <span id="rcpatroladmintools"></span></div>');                }                $("#rcpatrolbuttons").append('<div>Page tools: <span id="rcpatrolpagetools"></span></div>');                $("#rcpatroldiff").css({                    overflow: "auto"                });            })        }    }/** * Internationalization here */    rcpatrol.i18n = {        reasontorollback: {            en: 'Reason to rollback (optional)'        },        rollback: {            en: 'Rollback'        },        rollingback: {            en: 'Rolling back...'        },        rollbackfailed: {            en: 'Rollback failed'        },        rollbacksuccess: {            en: 'Rollback complete'        },        rollbacksummary: {            en: '[[w:User:Awesome Aasim/rcpatrol|RCP]] reverted edits by [[Special:Contributions/$2|$2]] ([[User_talk:$2|Talk]]); changed back to last revision by [[Special:Contributions/$1|$1]]'        },        warnsummary: {            en: '[[w:User:Awesome Aasim/rcpatrol|RCP]] send warning to $1 about [[$2]]'        },        reportsummary: {            en: '[[w:User:Awesome Aasim/rcpatrol|RCP]] report $1'        },        rollbacktitle: {            en: "Revert this user's edits",        },        previousedit: {            en: 'Previous edit'        },        previousedittitle: {            en: 'Load the previous edit in the batch'        },        nextedit: {            en: 'Next edit'        },        nextedittitle: {            en: 'Load the next edit in the batch'        },        refresh: {            en: 'Refresh'        },        connectionlost: {            en: 'Lost connection'        },        connectionlostdiffmessage: {            en: "Could not load diff.  Please check your Internet connection.  The diff will automatically reload when the connection is reestablished."        },        thank: {            en: 'Thank'        },        thanktitle: {            en: "Thank this user for their edits"        },        rollbackandwarn: {            en: 'Rollback and warn'        },        endoflist: {            en: 'Reached end of list.  Loading next batch...'        },        thankssent: {            en: 'Thanks sent!'        },        rcpatroltitle: {            en: 'Recent Changes Patrol'        },        rcpatroltitlewithdiff: {            en: 'Recent Changes Patrol "$1"'        },        delete: {            en: 'Delete'        },        protect: {            en: 'Protect'        },        block: {            en: 'Block poster'        },        history: {            en: 'View page history'        },        diff: {            en: 'View diff'        }    }    /**     * End of internationaliztaion.  DO NOT EDIT BELOW THIS LINE     */    rcpatrol.msgs = {};    for (var i in rcpatrol.i18n) {        rcpatrol.msgs[i] = rcpatrol.i18n[mw.config.get("wgUserLanguage")] ? rcpatrol.i18n[mw.config.get("wgUserLanguage")] : rcpatrol.i18n["en"]; //always fall back to English if the message translation is incomplete    }/** * Configuration for English Wiki How * Eventually this will be stored elsewhere on a separate page, maybe at [[Project:RC Patrol Script/config.js]] * The idea is that any particular modules that need to be disabled or reconfigured can be done so on a wiki by wiki basis by simply "reprogramming" it here. * The configuration file should be locked so that only administrators can edit it. */    rcpatrol.reportpage = "Wikipedia:Administrator intervention against vandalism"; //the page that users should be reported on    rcpatrol.reportstring = "\n\n* {{vandal|1=$1}} - $2"; //the string pattern to use for the report    rcpatrol.dropdown = [        {            keycode: 84, //t            val: "Test edit",            summary: "Test edit",            template: "uw-test"        },        {            keycode: 69, //e            val: "Disruptive edit",            summary: "[[WP:DE|Disruptive edit]]",            template: "uw-disruptive"        },        {            keycode: 77, //m            val: "Manual of style violation",            summary: "Violates [[WP:MOS|manual of style]]",            template: "uw-mos"        },        {            keycode: 65, //a            val: "Personal attack",            summary: "[[WP:NPA|Personal attack]]",            template: "uw-npa"        },        {            keycode: 76, //l            val: "BLP violation",            summary: "Violation of the [[WP:BLP|biographies of living people policy]]",            template: "uw-biog"        },        {            keycode: 78, //n            val: "Neutral point of view violation",            summary: "Violates [[WP:NPOV|neutral point of view]]",            template: "uw-npov"        },        {            keycode: 85, //u            val: "Unsourced",            summary: "[[WP:UNSOURCED|Unsourced]]",            template: "uw-unsourced"        },        {            keycode: 68, //d            val: "Unexplained content removal",            summary: "Unexplained removal of content",            template: "uw-delete"        },        {            keycode: 66, //b            val: "Page blanking",            summary: "Blanking the page",            template: "uw-blank"        },        {            keycode: 86, //v            val: "Vandalism",            summary: "Unconstructive edit",            template: "uw-vandalism"        },        {            keycode: 83, //s            val: "Link spam",            summary: "Inappropriate external link",            template: "uw-spam"        },        {            keycode: 80, //p            val: "Advertising",            summary: "Promotional language in article",            template: "uw-advert"        }    ];/** * Load all OOUI items, including buttons, etc. */    rcpatrol.rcpatrolbar = new OO.ui.HorizontalLayout({ align: 'inline' });    rcpatrol.rcpatrolbox = new OO.ui.TextInputWidget({        autosize: true,        placeholder: 'Reason to rollback (optional)',        icon: 'textSummary',        align: 'inline'    });    rcpatrol.rcpatrolbutton = new OO.ui.ButtonWidget({        autosize: true,        label: 'Rollback',        flags: [            'primary',            'progressive'        ],        icon: "editUndo",        align: 'inline'    });    rcpatrol.rollbackbar = new OO.ui.ActionFieldLayout(rcpatrol.rcpatrolbox, rcpatrol.rcpatrolbutton, { align: "inline" });    rcpatrol.previouseditbutton = new OO.ui.ButtonWidget({        autosize: true,        label: 'Previous edit',        icon: "previous",        align: 'inline'    });    rcpatrol.nexteditbutton = new OO.ui.ButtonWidget({        autosize: true,        label: 'Next edit',        icon: "next",        align: 'inline'    });    rcpatrol.fetchbutton = new OO.ui.ButtonWidget({        autosize: true,        label: 'Refresh',        icon: "reload",        align: 'inline'    });    rcpatrol.thankbutton = new OO.ui.ButtonWidget({        autosize: true,        label: 'Thank',        icon: "heart",        align: 'inline'    });    rcpatrol.patrolbutton = new OO.ui.ButtonWidget({        autosize: true,        label: 'Mark as patrolled',        icon: 'check',        align: 'inline'    });    rcpatrol.dropdownmenu = new OO.ui.DropdownWidget({        label: "Rollback and warn...",        icon: "speechBubbleAdd",        menu: {            items: []        }    });    rcpatrol.rcpatrolbar.addItems([        rcpatrol.previouseditbutton,        rcpatrol.nexteditbutton,        rcpatrol.fetchbutton,        rcpatrol.thankbutton,        rcpatrol.patrolbutton    ]);    rcpatrol.rcpatrolbutton.$element.attr("title", "Revert this user's edits [ctrl-alt R]");    rcpatrol.thankbutton.$element.attr("title", "Thank this user for their edits [ctrl-alt =]");    rcpatrol.patrolbutton.$element.attr("title", "Mark this edit as patrolled [ctrl-alt P]");    rcpatrol.nexteditbutton.$element.attr("title", "Load the next edit in the batch [ctrl-alt space]");    rcpatrol.previouseditbutton.$element.attr("title", "Load the previous edit in the batch [ctrl-alt ,]");    for (var i in rcpatrol.dropdown) {        var temp = new OO.ui.MenuOptionWidget({            data: rcpatrol.dropdown[i].keycode,            label: rcpatrol.dropdown[i].val        });        temp.$element.attr("title", rcpatrol.dropdown[i].val + (String.fromCharCode(rcpatrol.dropdown[i].keycode) ? " [ctrl-alt-shift " + String.fromCharCode(rcpatrol.dropdown[i].keycode) + "]" : ""));        rcpatrol.dropdownmenu.getMenu().addItems([temp]);    }    /**     * Disables/enables the RC patrol controls     * @param {*} bool whether to disable the controls or not     */    rcpatrol.setDisabled = function (bool) {        rcpatrol.isDisabled = bool;        rcpatrol.dropdownmenu.setDisabled(bool);        rcpatrol.previouseditbutton.setDisabled(bool);        rcpatrol.nexteditbutton.setDisabled(bool);        rcpatrol.rcpatrolbutton.setDisabled(bool);        rcpatrol.rcpatrolbox.setDisabled(bool);        rcpatrol.thankbutton.setDisabled(bool);        rcpatrol.patrolbutton.setDisabled(bool);        rcpatrol.fetchbutton.setDisabled(bool);    };    /**     * Fetches a list of recent changes and loads it onto RC patrol     */    rcpatrol.timeoutDuration = 1000;    rcpatrol.fetch = function () {        if (!rcpatrol.fetchbutton.isDisabled()) {            $("#rcpatroldiff").fadeOut();            rcpatrol.setDisabled(true);            $.get(mw.config.get("wgScriptPath") + "/api.php", {                "action": "query",                "format": "json",                "list": "recentchanges",                "rcprop": "title|timestamp|flags|loginfo|parsedcomment|user|ids|tags",                "rcshow": "!bot" + ((new URL(window.location.href)).searchParams.get("oresreview") ? "|oresreview" : ""),                "rctoponly": true,                "rclimit": "max",                "rctype": "edit|new",                "uselang": mw.config.get("wgUserLanguage")            }).done(function (result) {                if (result.error) {                    rcpatrol.timeoutDuration *= 2                    window.setTimeout(rcpatrol.fetch, rcpatrol.timeoutDuration / 2);                    console.error(result.error.info);                } else {                    rcpatrol.timeoutDuration = 1000                    rcpatrol.changes = result.query.recentchanges;                    console.log(result.query.recentchanges);                    rcpatrol.setDisabled(false);                    rcpatrol.currentChange = 0;                    rcpatrol.loadChange(rcpatrol.changes[rcpatrol.currentChange]);                }            }).fail(function () {                rcpatrol.timeoutDuration *= 2                window.setTimeout(rcpatrol.fetch, 1000);            });        }    };    /**     * Loads a change and places it in the RC patrol diff output.     * @param {*} change the diff of the change to load     */    rcpatrol.loadChange = function (change) {        $("#rcpatroldiff").fadeOut();        $("#rcpatroladmintools").fadeOut();        $("#rcpatrolpagetools").fadeOut();        rcpatrol.setDisabled(true);        $.get(mw.config.get("wgScriptPath") + "/api.php", {            "action": "query",            "format": "json",            "prop": "revisions",            "titles": change.title,            "rvlimit": "1",            "uselang": mw.config.get("wgUserLanguage")        }).done(function (result) {            for (var pageid in result.query.pages) {                change.revid = result.query.pages[pageid].revisions[0].revid;                change.user = result.query.pages[pageid].revisions[0].user;                break;            }            $.get(mw.config.get("wgScriptPath") + "/api.php", {                "action": "query",                "format": "json",                "prop": "revisions",                "titles": change.title,                "rvexcludeuser": change.user,                "rvlimit": "1",                "uselang": mw.config.get("wgUserLanguage")            }).done(function (result) {                console.log(result);                var oldid;                try {                    for (var pageid in result.query.pages) {                        oldid = result.query.pages[pageid].revisions[0].revid;                        break;                    }                } catch (Error) {                    var temp = oldid;                    oldid = change.revid;                    change.revid = "";                }                console.log(mw.config.get("wgScriptPath") + "/index.php?oldid=" + oldid + "&diff=" + change.revid);                var scriptpath = mw.config.get('wgScriptPath');                var loadurl = mw.config.get("wgScriptPath") + "/index.php?oldid=" + oldid + (change.revid ? "&diff=" + change.revid : "");                if (mw.config.get("wgMFMode")) {                    loadurl = mw.config.get("wgArticlePath").replace("$1", "Special:MobileDiff/" + oldid + (change.revid ? "..." + change.revid : ""));                }                $.get(loadurl, {                    safemode: "1",                    uselang: mw.config.get("wgUserLanguage"),                    useskin: mw.config.get("skin")                }).done(function (result) {                    var $r;                    $r = $(result);                    $("#rcpatroldiff").html($r.find("#mw-content-text").html());                    if (mw.config.get("wgMFMode")) {                        mw.loader.load("mobile.special.mobilediff.styles");                    } else {                        mw.loader.load("mediawiki.diff.styles");                    }                    $("#firstHeading, #section_0").html('Recent Changes Patrol \"<a target=\"_blank\" href=\"' + scriptpath + '/index.php?title=' + change.title + '\">' + change.title + "</a>\"");                    $("title").text("Recent Changes Patrol \"" + change.title + "\" - " + mw.config.get("wgSiteName"));                    $("#rcpatroldiff").fadeIn();                    $("#rcpatroladmintools").fadeIn();                    $("#rcpatrolpagetools").fadeIn();                    rcpatrol.rcpatrolbox.setValue("");                    rcpatrol.rcpatrolbutton.setLabel("Rollback");                    rcpatrol.patrolbutton.setLabel("Mark as patrolled");                    rcpatrol.setDisabled(false);                    $("#rcpatroladmintools").html('');                    $("#rcpatroladmintools").append('<a target="_blank" href="' + scriptpath + '/index.php?title=' + change.title + '&action=delete">Delete</a>');                    $("#rcpatroladmintools").append(' &bull; ');                    $("#rcpatroladmintools").append('<a target="_blank" href="' + scriptpath + '/index.php?title=' + change.title + '&action=protect">Protect</a>');                    $("#rcpatroladmintools").append(' &bull; ');                    $("#rcpatroladmintools").append('<a target="_blank" href="' + scriptpath + '/index.php?title=Special:Block/' + change.user + '">Block poster</a>');                    $("#rcpatrolpagetools").html('');                    $("#rcpatrolpagetools").append('<a target="_blank" href="' + scriptpath + '/index.php?title=' + change.title + '&action=history">View page history</a>');                    $("#rcpatrolpagetools").append(' &bull; ');                    $("#rcpatrolpagetools").append('<a target="_blank" href="' + scriptpath + '/index.php?oldid=' + oldid + '&diff=' + change.revid + '">View diff</a>');                }).fail(function () {                    $("#rcpatroldiff").fadeIn(1000);                    $("#rcpatroldiff").text("Could not load diff.  Please check your Internet connection.  The diff will automatically reload when the connection is reestablished.");                    window.setTimeout(function () {                        rcpatrol.loadChange(change);                    }, 1000);                });                /*                $("#rcpatroldiff").load(loadurl, function (response, status, xhr) {                    if (status == "error") {                    } else {                        $("#rcpatroldiff").find("form").hide();                        $("#rcpatroldiff").find("#firstHeading").hide();                    }                });                */            }).fail(function (result) {                $("#rcpatroldiff").fadeIn(1000);                $("#rcpatroldiff").text("Could not load diff.  Please check your Internet connection.  The diff will automatically reload when the connection is reestablished.");                window.setTimeout(function () {                    rcpatrol.loadChange(change)                }, 1000);            });        }).fail(function (result) {            $("#rcpatroldiff").fadeIn(1000);            $("#rcpatroldiff").text("Could not load diff.  Please check your Internet connection.  The diff will automatically reload when the connection is reestablished.");            window.setTimeout(function () {                rcpatrol.loadChange(change)            }, 1000);        });    };/** * Rolls back edits on diffs * @param {*} page the page to revert the edits on * @param {*} user the user to revert * @param {*} afterSuccess what to do after the revert is successful * @param {*} afterFail what to do if the revert fails */    rcpatrol.revert = function (page, user, afterSuccess, afterFail) {        if (!rcpatrol.rcpatrolbutton.isDisabled()) {            var summary = rcpatrol.rcpatrolbox.getValue();            rcpatrol.rcpatrolbutton.setLabel("Rolling back...");            rcpatrol.setDisabled(true);            $.get(mw.config.get("wgScriptPath") + "/api.php", {                "action": "query",                "format": "json",                "meta": "tokens",                "type": "rollback"            }).done(function (result) {                if (result.error) {                    rcpatrol.rcpatrolbutton.setLabel("Rollback failed");                    alert(result.error.info);                    afterFail();                } else {                    $.post(mw.config.get("wgScriptPath") + "/api.php", {                        "action": "rollback",                        "format": "json",                        "title": page,                        "token": result.query.tokens.rollbacktoken,                        "user": user,                        "summary": "[[User:Awesome Aasim/rcpatrol|RCP]] reverted edits by [[Special:Contributions/$2|$2]] ([[User_talk:$2|Talk]]); changed back to last revision by [[Special:Contributions/$1|$1]]" + (summary ? ": " + summary : "")                    }).done(function (result) {                        if (result.error) {                            rcpatrol.rcpatrolbutton.setLabel("Rollback failed");                            alert(result.error.info);                            afterFail();                        } else {                            rcpatrol.rcpatrolbutton.setLabel("Rollback complete");                            afterSuccess();                        }                    }).fail(function () {                        console.log(result);                        alert("Lost connection.");                        rcpatrol.rcpatrolbutton.setLabel("Rollback failed");                        afterFail();                    });                }            });        }    };/** * Warns a user with a specified warning template * @param {*} user the user to warn * @param {*} template the template prefix to use as a warning * @param {*} page the relevant page */    rcpatrol.warn = function (user, template, page, reason) {        var date = new Date();        var months = mw.config.get("wgMonthNames");        var currentMonth = months[date.getUTCMonth() + 1];        var year = date.getUTCFullYear();        var header = currentMonth + " " + year;        $.get(mw.config.get("wgScriptPath") + "/api.php", {            "action": "query",            "format": "json",            "meta": "tokens",            "type": "csrf",            "uselang": mw.config.get("wgUserLanguage")        }).done(function (result) {            var token = result.query.tokens.csrftoken;            $.get(mw.config.get("wgScriptPath") + "/api.php", {                "action": "parse",                "format": "json",                "prop": "text",                "page": "User_talk:" + user,                "uselang": mw.config.get("wgUserLanguage")            }).done(function (result) {                if (result.error) {                    if (result.error.code == "missingtitle") {                        $.post(mw.config.get("wgScriptPath") + "/api.php", {                            "action": "edit",                            "section": "new",                            "sectiontitle": header,                            "format": "json",                            "title": "User_talk:" + user,                            "text": "{{subst:" + template + "1|1=" + page + "}} ~~" + "~~",                            "summary": "[[User:Awesome Aasim/rcpatrol|RCP]] send warning to " + user + " about [[" + page + "]]",                            "token": token,                            "uselang": mw.config.get("wgUserLanguage")                        }).done(function (result) {                            if (result.error) {                                mw.notify("We could not send a warning to " + user + ".");                            } else {                                mw.notify("A warning was automatically sent to " + user + ".");                            }                        });                    }                } else {                    var section = "new";                    $(result.parse.text["*"]).find(".mw-headline").each(function (i) {                        if ($(this).text() == header) {                            section = i + 1;                        }                    });                    if (section == "new") {                        $.post(mw.config.get("wgScriptPath") + "/api.php", {                            "action": "edit",                            "section": "new",                            "sectiontitle": header,                            "format": "json",                            "title": "User_talk:" + user,                            "text": "{{subst:" + template + "1|1=" + page + "}} ~~" + "~~",                            "summary": "[[User:Awesome Aasim/rcpatrol|RCP]] send warning to " + user + " about [[" + page + "]]",                            "token": token,                            "uselang": mw.config.get("wgUserLanguage")                        }).done(function (result) {                            if (result.error) {                                mw.notify("We could not send a warning to " + user + ".");                            } else {                                mw.notify("A warning was automatically sent to " + user + ".");                            }                        });                    } else {                        $.get(mw.config.get("wgScriptPath") + "/api.php", {                            "action": "parse",                            "section": section,                            "format": "json",                            "prop": "wikitext",                            "page": "User_talk:" + user,                            "uselang": mw.config.get("wgUserLanguage")                        }).done(function (result) {                            if (result.error) {                                console.error(result.error.info);                            } else {                                console.log(result.parse.wikitext["*"]);                                var warninglevelstrings = result.parse.wikitext["*"].match(/<!--( ){0,}Template:.*(1|2|3|4)(im)?( ){0,}-->/g);                                console.log(warninglevelstrings);                                var warninglevels = warninglevelstrings[warninglevelstrings.length - 1].match(/[(1|2|3|4)]/);                                var warninglevel = parseInt(warninglevels[warninglevels.length - 1]) + 1;                                var oldtimestamp = (new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()) - 86400000)).toISOString();                                $.get(mw.config.get("wgScriptPath") + "/api.php", {                                    "action": "query",                                    "format": "json",                                    "prop": "revisions",                                    "titles": "User_talk:" + user,                                    "rvsection": section,                                    "rvend": oldtimestamp,                                    "uselang": mw.config.get("wgUserLanguage")                                }).done(function (result) {                                    var revisions = [];                                    try {                                        for (var pageid in result.query.pages) {                                            revisions = result.query.pages[pageid].revisions;                                        }                                    } catch (Error) {                                    }                                    if (revisions) {                                        if (warninglevel > 4) {                                            rcpatrol.report(user, reason);                                        } else {                                            $.post(mw.config.get("wgScriptPath") + "/api.php", {                                                "action": "edit",                                                "section": section,                                                "sectiontitle": header,                                                "format": "json",                                                "title": "User_talk:" + user,                                                "appendtext": "\n\n{{subst:" + template + warninglevel + "|1=" + page + "}} ~~" + "~~",                                                "summary": "[[User:Awesome Aasim/rcpatrol|RCP]] send warning to " + user + " about [[" + page + "]]",                                                "token": token,                                                "uselang": mw.config.get("wgUserLanguage")                                            }).done(function (result) {                                                if (result.error) {                                                    mw.notify("We could not send a warning to " + user + ".");                                                } else {                                                    mw.notify("A warning was automatically sent to " + user + ".");                                                }                                            });                                        }                                    } else {                                        $.post(mw.config.get("wgScriptPath") + "/api.php", {                                            "action": "edit",                                            "section": section,                                            "sectiontitle": header,                                            "format": "json",                                            "title": "User_talk:" + user,                                            "appendtext": "\n\n{{subst:" + template + "1|1=" + page + "}} ~~" + "~~",                                            "summary": "[[User:Awesome Aasim/rcpatrol|RCP]] send warning to " + user + " about [[" + page + "]]",                                            "token": token,                                            "uselang": mw.config.get("wgUserLanguage")                                        }).done(function (result) {                                            if (result.error) {                                                mw.notify("We could not send a warning to " + user + ".");                                            } else {                                                mw.notify("A warning was automatically sent to " + user + ".");                                            }                                        });                                    }                                });                            }                        });                    }                }            });        });    };/** * Reports any user to a preconfigured project page * If admin, blocks the user for a preset time * @param {*} user user to report */    rcpatrol.report = function (user, reason) {        if (mw.config.get("wgUserGroups").includes("sysop")) {            //TODO:  get block suggestion for vandals 1 day initially, then double the block if the user commits another infraction after getting unblocked            //also:  block API            var blockwindow = window.open(mw.config.get("wgArticlePath").replace("$1", "Special:Block/" + user) + "?wpReason-other=" + encodeURI(reason));            blockwindow.onload = function () {                alert("The user has received a final warning in the last 24 hours, so this window was opened.  When you are done blocking the user, you can close this tab and go back to RC patrol.");            }        } else {            var reportwindow = window.open(mw.config.get("wgArticlePath").replace("$1", rcpatrol.reportpage));            reportwindow.onload = function () {                var reportinfo = reportwindow.prompt("This user has received a final warning in the last 24 hours or was recently unblocked, so RC patrol is proceeding to report to AIV. Enter information about the report here, leave blank for \"" + reason + ": after final warning.\". If you think a report is inappropriate, click 'Cancel' and proceed to report on your own accord.");                if (reportinfo == null || reportinfo == undefined) return;                reportinfo = reportinfo ? reportinfo : reason + ": after final warning.";                $.get(mw.config.get("wgScriptPath") + "/api.php", {                    "action": "query",                    "format": "json",                    "meta": "tokens",                    "type": "csrf",                    "uselang": mw.config.get("wgUserLanguage")                }).done(function (result) {                    $.post(mw.config.get("wgScriptPath") + "/api.php", {                        "action": "edit",                        "format": "json",                        "title": rcpatrol.reportpage,                        "summary": "[[User:Awesome Aasim/rcpatrol|RCP]] report " + user,                        "appendtext": rcpatrol.reportstring.replace("$1", user).replace("$2", reportinfo) + " ~~" + "~~",                        "uselang": mw.config.get("wgUserLanguage"),                        "token": result.query.tokens.csrftoken                    }).done(function (result) {                        if (result.error) {                            reportwindow.alert(result.error.info);                        } else {                            mw.notify("User successfully reported to admins.");                        }                        reportwindow.close();                    });                });            }        }    }/** * Handles global events, including clicks, keypresses, etc. */    rcpatrol.fetchbutton.$element.click(rcpatrol.fetch);    rcpatrol.rcpatrolbutton.$element.click(function (e) {        rcpatrol.revert(rcpatrol.changes[rcpatrol.currentChange].title, rcpatrol.changes[rcpatrol.currentChange].user, function () {            rcpatrol.currentChange++;            rcpatrol.loadChange(rcpatrol.changes[rcpatrol.currentChange]);        },            function () {                rcpatrol.loadChange(rcpatrol.changes[rcpatrol.currentChange]);            });    });    rcpatrol.nexteditbutton.$element.click(function (e) {        if (!rcpatrol.nexteditbutton.isDisabled()) {            e.preventDefault();            rcpatrol.currentChange++;            if (rcpatrol.currentChange >= rcpatrol.changes.length) {                mw.notify("Reached end of list.  Loading next batch...")                rcpatrol.fetch();            } else {                rcpatrol.loadChange(rcpatrol.changes[rcpatrol.currentChange]);            }        }    });    rcpatrol.previouseditbutton.$element.click(function (e) {        if (!rcpatrol.previouseditbutton.isDisabled()) {            e.preventDefault();            rcpatrol.currentChange--;            if (rcpatrol.currentChange < 0) {                rcpatrol.currentChange = 0;            }            rcpatrol.loadChange(rcpatrol.changes[rcpatrol.currentChange]);        }    });    rcpatrol.thankbutton.$element.click(function (e) {        if (!rcpatrol.thankbutton.isDisabled()) {            e.preventDefault();            rcpatrol.thankbutton.setDisabled(true);            $.get(mw.config.get("wgScriptPath") + "/api.php", {                "action": "query",                "format": "json",                "meta": "tokens",                "type": "csrf"            }).done(function (result) {                $.post(mw.config.get("wgScriptPath") + "/api.php", {                    "action": "thank",                    "format": "json",                    "rev": rcpatrol.changes[rcpatrol.currentChange].revid,                    "token": result.query.tokens.csrftoken                }).done(function (result) {                    if (result.error) {                        alert(result.error.info);                    } else {                        mw.notify("Thanks sent!");                    }                })            })        }    });    /**     * Mark the edit as patrolled     **/    rcpatrol.patrolbutton.$element.click(function (e) {        rcpatrol.patrolbutton.setLabel('Marking as patrolled');        if (!rcpatrol.patrolbutton.isDisabled()) {            e.preventDefault();            rcpatrol.patrolbutton.setDisabled(true);            $.get(mw.config.get("wgScriptPath") + "/api.php", {                "action": "query",                "format": "json",                "meta": "tokens",                "type": "patrol"            }).done(function (result) {                $.post(mw.config.get("wgScriptPath") + "/api.php", {                    "action": "patrol",                    "format": "json",                    "rcid": rcpatrol.changes[rcpatrol.currentChange].rcid,                    "token": result.query.tokens.patroltoken,                    "formatversion": 2                }).done(function (result) {                    if (result.error) {                        mw.notify(result.error.info);                    } else {                        mw.notify("The version (rcid " + rcpatrol.changes[rcpatrol.currentChange].rcid + ") has been marked as patrolled!");                        rcpatrol.patrolbutton.setLabel('Marked as patrolled');                    }                })            })        }    })    rcpatrol.rcpatrolbox.$element.keypress(function (e) {        if (e.which == 13) {            rcpatrol.revert(rcpatrol.changes[rcpatrol.currentChange].title, rcpatrol.changes[rcpatrol.currentChange].user, function () {                rcpatrol.currentChange++;                rcpatrol.loadChange(rcpatrol.changes[rcpatrol.currentChange]);            },                function () {                    rcpatrol.loadChange(rcpatrol.changes[rcpatrol.currentChange]);                });        }    });    rcpatrol.dropdownmenu.getMenu().on('select', function () {        var val = rcpatrol.dropdownmenu.getLabel();        for (var option of rcpatrol.dropdown) {            if (option.val == val) {                rcpatrol.rcpatrolbox.setValue(option.summary);                rcpatrol.revert(rcpatrol.changes[rcpatrol.currentChange].title, rcpatrol.changes[rcpatrol.currentChange].user, function () {                    rcpatrol.warn(rcpatrol.changes[rcpatrol.currentChange].user, option.template, rcpatrol.changes[rcpatrol.currentChange].title, option.val);                    rcpatrol.currentChange++;                    rcpatrol.loadChange(rcpatrol.changes[rcpatrol.currentChange]);                    rcpatrol.dropdownmenu.getMenu().unselectItem();                    rcpatrol.dropdownmenu.setLabel("Rollback and warn...");                }, function () {                    rcpatrol.dropdownmenu.getMenu().unselectItem();                    rcpatrol.dropdownmenu.setLabel("Rollback and warn...");                    rcpatrol.loadChange(rcpatrol.changes[rcpatrol.currentChange]);                });                break;            } else {                continue;            }        }    });    /**     * Page for processing key combinations     */    $(document).keydown(function (e) {        if (e.ctrlKey && e.altKey && !e.shiftKey) {            switch (e.which) {                case 82: e.preventDefault(); //rollback (r)                    rcpatrol.revert(rcpatrol.changes[rcpatrol.currentChange].title, rcpatrol.changes[rcpatrol.currentChange].user, function () {                        rcpatrol.currentChange++;                        rcpatrol.loadChange(rcpatrol.changes[rcpatrol.currentChange]);                    },                        function () {                            rcpatrol.loadChange(rcpatrol.changes[rcpatrol.currentChange]);                        });                    break;                case 80: e.preventDefault(); //patrol (p)                    rcpatrol.patrolbutton.$element.click();                    break;                case 32: e.preventDefault(); //next edit ( )                    rcpatrol.nexteditbutton.$element.click();                    break;                case 188: e.preventDefault(); //previous edit (<)                    rcpatrol.previouseditbutton.$element.click();                    break;                case 187: e.preventDefault(); //thanks (+)                    rcpatrol.thankbutton.$element.click();                    break;            }        } else if (e.ctrlKey && e.altKey && e.shiftKey) {            for (var option of rcpatrol.dropdown) {                if (option.keycode == e.which) {                    rcpatrol.rcpatrolbox.setValue(option.summary);                    rcpatrol.revert(rcpatrol.changes[rcpatrol.currentChange].title, rcpatrol.changes[rcpatrol.currentChange].user, function () {                        rcpatrol.warn(rcpatrol.changes[rcpatrol.currentChange].user, option.template, rcpatrol.changes[rcpatrol.currentChange].title, option.val);                        rcpatrol.currentChange++;                        rcpatrol.loadChange(rcpatrol.changes[rcpatrol.currentChange]);                    }, function () {                        rcpatrol.loadChange(rcpatrol.changes[rcpatrol.currentChange]);                    });                    break;                } else {                    continue;                }            }        }    });})