From Wikipedia, the free encyclopedia
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 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.

**/

// <nowiki>



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 (!rcpatrol) { // stops multiple instances of RC patrol from running

        //necessary resources

        var 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

             */

            if (mw.config.get("skin") == "vector" && !(new URL(location.href)).searchParams.get("useskinversion")) {

                window.location.replace((function () {

                    var url = (new URL(location.href));

                    url.searchParams.set("useskinversion", "2");

                    return url;

                })());

            }

            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="/wiki/Special:BlankPage/RCPatrol?oresreview=1">Only show edits that likely need review</a><br>');

                if (mw.config.get('wgUserGroups').includes('sysop')) {

                    $("#rcpatrolbuttons").append('Admin tools: <span id="rcpatroladmintools"></span>');

                }

                $("#rcpatrolbuttons").append('Page tools: <span id="rcpatrolpagetools"></span>');

                $("#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.msgsi = rcpatrol.i18nmw.config.get("wgUserLanguage")] ? rcpatrol.i18nmw.config.get("wgUserLanguage")] : rcpatrol.i18n"en"]; //always fall back to English if the message translation is incomplete

    }

    /**

     * Configuration for English Wikipedia

     * 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.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.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.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.dropdowni].keycode,

            label: rcpatrol.dropdowni].val

        });

        temp.$element.attr("title", rcpatrol.dropdowni].val + (String.fromCharCode(rcpatrol.dropdowni].keycode) ? " [ctrl-alt " + String.fromCharCode(rcpatrol.dropdowni].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.fetchbutton.setDisabled(bool);

    };

    /**

     * Fetches a list of recent changes and loads it onto RC patrol

     */

    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) {

                rcpatrol.changes = result.query.recentchanges;

                console.log(result.query.recentchanges);

                rcpatrol.setDisabled(false);

                rcpatrol.currentChange = 0;

                rcpatrol.loadChange(rcpatrol.changesrcpatrol.currentChange]);

            }).fail(function () {

                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.pagespageid].revisions0].revid;

                change.user = result.query.pagespageid].revisions0].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.pagespageid].revisions0].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 (location.href.split(".").includes("m")) {

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

                    useskinversion: "2"

                }).done(function (result) {

                    var contenttextlocation;

                    switch (mw.config.get("skin")) {

                        case "timeless": contenttextlocation = '#mw-wrapper';

                            break;

                        case "vector": contenttextlocation = "#content, .mw-page-container";

                            break;

                        case "monobook": contenttextlocation = "#globalWrapper";

                            break;

                        case "minerva": contenttextlocation = "#mw-mf-viewport"

                            break;

                        case "modern": contenttextlocation = "#mw_main";

                            break;

                    }

                    var $r = $(result);

                    $("#rcpatroldiff").html($r);

                    $("#rcpatroldiff").find(contenttextlocation).html($("#rcpatroldiff").find("#mw-content-text").html());



                    $("#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.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) {

        var date = new Date();

        var months = mw.config.get("wgMonthNames");

        var currentMonth = monthsdate.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 = warninglevelstringswarninglevelstrings.length - 1].match(/[(1|2|3|4)]/);

                                var warninglevel = parseInt(warninglevelswarninglevels.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.pagespageid].revisions;

                                        }

                                    } catch (Error) {



                                    }

                                    if (revisions) {

                                        if (warninglevel > 4) {

                                            rcpatrol.report(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 + 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) {



        if (mw.config.get("wgUserGroups").includes("sysop")) {

            //TODO:  get block suggestion for vandals (24 hrs for first block, 72 hrs for second block, 3^(n-1) days for the (nth block))

            //also:  block API

            var blockwindow = window.open(mw.config.get("wgArticlePath").replace("$1", "Special:Block/" + user));

            blockwindow.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 reportinfo = prompt("Enter information about the report here: ");

            reportinfo = reportinfo ? reportinfo : "Vandalism 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")

                }).done(function (result) {

                    if (result.error) {

                        alert(result.error.info);

                    } else {

                        mw.notify("User successfully reported to admins.");

                    }

                });

            });

        }

    }

    /**

     * Handles global events, including clicks, keypresses, etc.

     */

    rcpatrol.fetchbutton.$element.click(rcpatrol.fetch);

    rcpatrol.rcpatrolbutton.$element.click(function (e) {

        rcpatrol.revert(rcpatrol.changesrcpatrol.currentChange].title, rcpatrol.changesrcpatrol.currentChange].user, function () {

            rcpatrol.currentChange++;

            rcpatrol.loadChange(rcpatrol.changesrcpatrol.currentChange]);

        },

            function () {

                rcpatrol.loadChange(rcpatrol.changesrcpatrol.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.changesrcpatrol.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.changesrcpatrol.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.changesrcpatrol.currentChange].revid,

                    "token": result.query.tokens.csrftoken

                }).done(function (result) {

                    if (result.error) {

                        alert(result.error.info);

                    } else {

                        mw.notify("Thanks sent!");

                    }

                })

            })

        }

    })

    rcpatrol.rcpatrolbox.$element.keypress(function (e) {



        if (e.which == 13) {

            rcpatrol.revert(rcpatrol.changesrcpatrol.currentChange].title, rcpatrol.changesrcpatrol.currentChange].user, function () {

                rcpatrol.currentChange++;

                rcpatrol.loadChange(rcpatrol.changesrcpatrol.currentChange]);

            },

                function () {

                    rcpatrol.loadChange(rcpatrol.changesrcpatrol.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.changesrcpatrol.currentChange].title, rcpatrol.changesrcpatrol.currentChange].user, function () {

                    rcpatrol.warn(rcpatrol.changesrcpatrol.currentChange].user, option.template, rcpatrol.changesrcpatrol.currentChange].title);

                    rcpatrol.currentChange++;

                    rcpatrol.loadChange(rcpatrol.changesrcpatrol.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.changesrcpatrol.currentChange]);

                });

                break;

            } else {

                continue;

            }

        }

    });

    /**

     * Page for processing key combinations

     */



    $(document).keydown(function (e) {

        if (e.ctrlKey && e.altKey) {

            switch (e.which) {

                case 82: e.preventDefault(); //rollback (r)

                    rcpatrol.revert(rcpatrol.changesrcpatrol.currentChange].title, rcpatrol.changesrcpatrol.currentChange].user, function () {

                        rcpatrol.currentChange++;

                        rcpatrol.loadChange(rcpatrol.changesrcpatrol.currentChange]);

                    },

                        function () {

                            rcpatrol.loadChange(rcpatrol.changesrcpatrol.currentChange]);

                        });

                    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;

                default:

                    for (var option of rcpatrol.dropdown) {

                        if (option.keycode == e.which) {

                            rcpatrol.rcpatrolbox.setValue(option.summary);

                            rcpatrol.revert(rcpatrol.changesrcpatrol.currentChange].title, rcpatrol.changesrcpatrol.currentChange].user, function () {

                                rcpatrol.warn(rcpatrol.changesrcpatrol.currentChange].user, option.template, rcpatrol.changesrcpatrol.currentChange].title);

                                rcpatrol.currentChange++;

                                rcpatrol.loadChange(rcpatrol.changesrcpatrol.currentChange]);

                            }, function () {

                                rcpatrol.loadChange(rcpatrol.changesrcpatrol.currentChange]);

                            });

                            break;

                        } else {

                            continue;

                        }

                    }

                    break;

            }

        }

    });

});

// </nowiki>
From Wikipedia, the free encyclopedia
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 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.

**/

// <nowiki>



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 (!rcpatrol) { // stops multiple instances of RC patrol from running

        //necessary resources

        var 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

             */

            if (mw.config.get("skin") == "vector" && !(new URL(location.href)).searchParams.get("useskinversion")) {

                window.location.replace((function () {

                    var url = (new URL(location.href));

                    url.searchParams.set("useskinversion", "2");

                    return url;

                })());

            }

            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="/wiki/Special:BlankPage/RCPatrol?oresreview=1">Only show edits that likely need review</a><br>');

                if (mw.config.get('wgUserGroups').includes('sysop')) {

                    $("#rcpatrolbuttons").append('Admin tools: <span id="rcpatroladmintools"></span>');

                }

                $("#rcpatrolbuttons").append('Page tools: <span id="rcpatrolpagetools"></span>');

                $("#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.msgsi = rcpatrol.i18nmw.config.get("wgUserLanguage")] ? rcpatrol.i18nmw.config.get("wgUserLanguage")] : rcpatrol.i18n"en"]; //always fall back to English if the message translation is incomplete

    }

    /**

     * Configuration for English Wikipedia

     * 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.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.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.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.dropdowni].keycode,

            label: rcpatrol.dropdowni].val

        });

        temp.$element.attr("title", rcpatrol.dropdowni].val + (String.fromCharCode(rcpatrol.dropdowni].keycode) ? " [ctrl-alt " + String.fromCharCode(rcpatrol.dropdowni].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.fetchbutton.setDisabled(bool);

    };

    /**

     * Fetches a list of recent changes and loads it onto RC patrol

     */

    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) {

                rcpatrol.changes = result.query.recentchanges;

                console.log(result.query.recentchanges);

                rcpatrol.setDisabled(false);

                rcpatrol.currentChange = 0;

                rcpatrol.loadChange(rcpatrol.changesrcpatrol.currentChange]);

            }).fail(function () {

                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.pagespageid].revisions0].revid;

                change.user = result.query.pagespageid].revisions0].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.pagespageid].revisions0].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 (location.href.split(".").includes("m")) {

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

                    useskinversion: "2"

                }).done(function (result) {

                    var contenttextlocation;

                    switch (mw.config.get("skin")) {

                        case "timeless": contenttextlocation = '#mw-wrapper';

                            break;

                        case "vector": contenttextlocation = "#content, .mw-page-container";

                            break;

                        case "monobook": contenttextlocation = "#globalWrapper";

                            break;

                        case "minerva": contenttextlocation = "#mw-mf-viewport"

                            break;

                        case "modern": contenttextlocation = "#mw_main";

                            break;

                    }

                    var $r = $(result);

                    $("#rcpatroldiff").html($r);

                    $("#rcpatroldiff").find(contenttextlocation).html($("#rcpatroldiff").find("#mw-content-text").html());



                    $("#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.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) {

        var date = new Date();

        var months = mw.config.get("wgMonthNames");

        var currentMonth = monthsdate.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 = warninglevelstringswarninglevelstrings.length - 1].match(/[(1|2|3|4)]/);

                                var warninglevel = parseInt(warninglevelswarninglevels.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.pagespageid].revisions;

                                        }

                                    } catch (Error) {



                                    }

                                    if (revisions) {

                                        if (warninglevel > 4) {

                                            rcpatrol.report(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 + 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) {



        if (mw.config.get("wgUserGroups").includes("sysop")) {

            //TODO:  get block suggestion for vandals (24 hrs for first block, 72 hrs for second block, 3^(n-1) days for the (nth block))

            //also:  block API

            var blockwindow = window.open(mw.config.get("wgArticlePath").replace("$1", "Special:Block/" + user));

            blockwindow.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 reportinfo = prompt("Enter information about the report here: ");

            reportinfo = reportinfo ? reportinfo : "Vandalism 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")

                }).done(function (result) {

                    if (result.error) {

                        alert(result.error.info);

                    } else {

                        mw.notify("User successfully reported to admins.");

                    }

                });

            });

        }

    }

    /**

     * Handles global events, including clicks, keypresses, etc.

     */

    rcpatrol.fetchbutton.$element.click(rcpatrol.fetch);

    rcpatrol.rcpatrolbutton.$element.click(function (e) {

        rcpatrol.revert(rcpatrol.changesrcpatrol.currentChange].title, rcpatrol.changesrcpatrol.currentChange].user, function () {

            rcpatrol.currentChange++;

            rcpatrol.loadChange(rcpatrol.changesrcpatrol.currentChange]);

        },

            function () {

                rcpatrol.loadChange(rcpatrol.changesrcpatrol.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.changesrcpatrol.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.changesrcpatrol.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.changesrcpatrol.currentChange].revid,

                    "token": result.query.tokens.csrftoken

                }).done(function (result) {

                    if (result.error) {

                        alert(result.error.info);

                    } else {

                        mw.notify("Thanks sent!");

                    }

                })

            })

        }

    })

    rcpatrol.rcpatrolbox.$element.keypress(function (e) {



        if (e.which == 13) {

            rcpatrol.revert(rcpatrol.changesrcpatrol.currentChange].title, rcpatrol.changesrcpatrol.currentChange].user, function () {

                rcpatrol.currentChange++;

                rcpatrol.loadChange(rcpatrol.changesrcpatrol.currentChange]);

            },

                function () {

                    rcpatrol.loadChange(rcpatrol.changesrcpatrol.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.changesrcpatrol.currentChange].title, rcpatrol.changesrcpatrol.currentChange].user, function () {

                    rcpatrol.warn(rcpatrol.changesrcpatrol.currentChange].user, option.template, rcpatrol.changesrcpatrol.currentChange].title);

                    rcpatrol.currentChange++;

                    rcpatrol.loadChange(rcpatrol.changesrcpatrol.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.changesrcpatrol.currentChange]);

                });

                break;

            } else {

                continue;

            }

        }

    });

    /**

     * Page for processing key combinations

     */



    $(document).keydown(function (e) {

        if (e.ctrlKey && e.altKey) {

            switch (e.which) {

                case 82: e.preventDefault(); //rollback (r)

                    rcpatrol.revert(rcpatrol.changesrcpatrol.currentChange].title, rcpatrol.changesrcpatrol.currentChange].user, function () {

                        rcpatrol.currentChange++;

                        rcpatrol.loadChange(rcpatrol.changesrcpatrol.currentChange]);

                    },

                        function () {

                            rcpatrol.loadChange(rcpatrol.changesrcpatrol.currentChange]);

                        });

                    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;

                default:

                    for (var option of rcpatrol.dropdown) {

                        if (option.keycode == e.which) {

                            rcpatrol.rcpatrolbox.setValue(option.summary);

                            rcpatrol.revert(rcpatrol.changesrcpatrol.currentChange].title, rcpatrol.changesrcpatrol.currentChange].user, function () {

                                rcpatrol.warn(rcpatrol.changesrcpatrol.currentChange].user, option.template, rcpatrol.changesrcpatrol.currentChange].title);

                                rcpatrol.currentChange++;

                                rcpatrol.loadChange(rcpatrol.changesrcpatrol.currentChange]);

                            }, function () {

                                rcpatrol.loadChange(rcpatrol.changesrcpatrol.currentChange]);

                            });

                            break;

                        } else {

                            continue;

                        }

                    }

                    break;

            }

        }

    });

});

// </nowiki>

Videos

Youtube | Vimeo | Bing

Websites

Google | Yahoo | Bing

Encyclopedia

Google | Yahoo | Bing

Facebook