Thành viên:NgocAnMaster/Gadget-SBHandler.js

Bách khoa toàn thư mở Wikipedia

Chú ý: Sau khi lưu thay đổi trang, bạn phải xóa bộ nhớ đệm của trình duyệt để nhìn thấy các thay đổi. Google Chrome, Firefox, Internet ExplorerSafari: Giữ phím ⇧ Shift và nhấn nút Reload/Tải lại trên thanh công cụ của trình duyệt. Để biết chi tiết và hướng dẫn cho các trình duyệt khác, xem Trợ giúp:Xóa bộ nhớ đệm.

/* Nguồn: [[:m:MediaWiki:Gadget-SBHandler.js]] */
/**
 * Support for quick handling of the [[Spam blacklist]] at meta.
 * See [[:m:User:Erwin/SBHandler]] for more information.
 * Tested only in Firefox.
 *
 * Author: [[:m:User:Erwin]], October 2008 - February 2009
 * License: Quadruple licensed GFDL, GPL, LGPL and Creative Commons Attribution 3.0 (CC-BY-3.0)
 *
 * Version history:
 *
 * - This tool uses code from DelReqHandler at Commons.
 *   [[:Commons:MediaWiki:Gadget-DelReqHandler.js]] (oldid=15093612)
 *   Author: [[:Commons:User:Lupo]], October 2007 - January 2008
 *   License: Quadruple licensed GFDL, GPL, LGPL and Creative Commons Attribution 3.0 (CC-BY-3.0)
 *
 * - Script adapted to account for change in section edit links -- [[m:user:billinghurst]] 2013-05
 *
 * - User sDrewth reported the script is broken. -- 2013-11-27
 *
 * - Cleaned up to pass JSHint, and migrated use of (now deprecated) legacy wikibits to
 *   jQuery and newer MediaWiki core built-in javascript libraries. --Krinkle 2013-11-28
 */
/*jshint unused:true, eqnull:true, browser:true, white:true, indent:4 */
/*global mw, $ */
/*global SBHandlerAddComment, SBHandlerRemComment, SBHandlerCloseComment, SBHandlerRevComment, SBHandlerDecComment */
// <nowiki>
(function () {
    // Guard against double inclusions
    if (typeof window.SBHandler !== 'undefined') {
        return;
    }

    var conf = mw.config.get([
        'wgUserGroups',
        'wgPageName',
        'wgServer',
        'wgScriptPath',
        'wgUserName'
    ]);

    var action, urls, params, logtitle, tprevid, log_text, summary;

    var SBrequest;
    var SBdebug;

    var SBlist;
    var SBlog;

    var SBUtils = {
        // userIsInGroup (from Commons:MediaWiki:Utilities.js)
        userIsInGroup: function (group) {
            if (conf.wgUserGroups) {
                if (!group || group.length === 0) {
                    group = '*';
                }
                for (var i = 0; i < conf.wgUserGroups.length; i++) {
                    if (conf.wgUserGroups[i] === group) {
                        return true;
                    }
                }
            }
            return false;
        },

        // setEditSummary (from Commons:MediaWiki:Utilities.js)
        setEditSummary: function (text) {
            if (document.editform == null || document.editform.wpSummary == null) {
                return;
            }
            var summary = document.editform.wpSummary.value;
            if (summary == null || summary.length === 0) {
                document.editform.wpSummary.value = text;
            } else if (summary.substr(-3) === '*/ ' || summary.substr(-2) === '*/') {
                document.editform.wpSummary.value += text;
            } else {
                document.editform.wpSummary.value += '; ' + text;
            }
        },

        // makeRawLink (from Commons:MediaWiki:Utilities.js)
        makeRawLink: function (name, url, target) {
            var link = document.createElement('a');
            link.setAttribute('href', url);
            if (target) {
                link.setAttribute('target', target);
            }
            link.appendChild(document.createTextNode(name));
            return link;
        },

        // The following function is defined in several places, and unfortunately, it is defined
        // wrongly in some places. (For instance, in [[:en:User:Lupin/popups.js]]: it should use
        // decodeURIComponent, not decodeURI!!!) Make sure we've got the right version here:
        getParamValue: function (paramName) {
            var cmdRe = new RegExp('[&?]' + paramName + '=([^&]*)');
            var m = cmdRe.exec(document.location.href);
            if (m) {
                try {
                    return decodeURIComponent(m[1]);
                } catch (someError) {}
            }
            return null;
        }
    };

    /**** Enable the whole shebang only for sysops and stewards. */
    var SBHandler;
    if (SBUtils.userIsInGroup('sysop') || SBUtils.userIsInGroup('steward')) {

        SBHandler = {

            /*------------------------------------------------------------------------------------------
            Spam blacklist requests closing: add "[add]", "[remove]", "[reverted]" and "[decline]" links to
            the left of the section edit links of a request.
            ------------------------------------------------------------------------------------------*/

            sb_close_add: 'close_add',
            sb_close_rem: 'close_rem',
            sb_close_na: 'close_na',
            sb_close_rev: 'close_rev',
            sb_close_dec: 'close_dec',
            sb_close_decperen: 'close_dec_peren',
            close_add_summary: 'Đã thêm',
            close_rem_summary: 'Đã loại bỏ',
            close_na_summary: 'Đã đóng',
            close_ignore_summary: 'Đã bỏ qua',
            close_rev_summary: 'Đã lùi lại',
            close_dec_summary: 'Đã từ chối',
            sb_add: 'add',
            sb_rem: 'rem',

            closeRequestLinks: function () {
                function addRequestLinks(name, href, before, parent) {
                    parent.insertBefore(document.createTextNode('['), before);
                    parent.insertBefore(SBUtils.makeRawLink(name, href), before);
                    parent.insertBefore(document.createTextNode(']'), before);
                }

                var param = SBUtils.getParamValue('fakeaction');
                var wpAction = SBUtils.getParamValue('action');
                var edit_lks, anchors, ignore;
                var anchor, href, orig_bracket, title, lk_name, lk_action;
                if (param == null) {
                    if (conf.wgPageName === 'Wikipedia:Yêu_cầu_thay_đổi_danh_sách_đen_về_spam') {
                        // We're on [[Wikipedia:Yêu cầu thay đổi danh sách đen về spam]]
                        edit_lks = $('span.mw-editsection').toArray();
                        if (edit_lks.length === 0) {
                            return;
                        }
                        for (i = 0; i < edit_lks.length; i++) {
                            // Set to true if the addition or removal section is found
                            ignore = false;
                            // Find the A within:
                            anchors = edit_lks[i].getElementsByTagName('a');
                            if (anchors != null && anchors.length > 0) {
                                anchor = anchors[0];
                                href = anchor.getAttribute('href');
                                title = anchor.getAttribute('title');
                                if (title.indexOf('additions') > 0 && title.indexOf('Bot') < 0) {
                                    ignore = true;
                                    lk_name = 'add';
                                    lk_action = SBHandler.sb_close_add;
                                } else if (title.indexOf('additions') > 0 && title.indexOf('Bot') > 0) {
                                    lk_name = null;
                                    lk_action = null;
                                } else if (title.indexOf('removals') > 0) {
                                    ignore = true;
                                    lk_name = 'remove';
                                    lk_action = SBHandler.sb_close_rem;
                                } else if (title.indexOf('problems') > 0) {
                                    lk_name = null;
                                    lk_action = null;
                                }
                                if (href.indexOf('Wikipedia:Yêu_cầu_thay_đổi_danh_sách_đen_về_spam') > 0 && href.indexOf('&section=') > 0 && lk_name != null && !ignore) {
                                    orig_bracket = edit_lks[i].firstChild;
                                    addRequestLinks(lk_name, href + '&fakeaction=' + lk_action, orig_bracket, edit_lks[i]);
                                    addRequestLinks('decline', href + '&fakeaction=' + SBHandler.sb_close_dec, orig_bracket, edit_lks[i]);
                                    addRequestLinks('decline-peren', href + '&fakeaction=' + SBHandler.sb_close_decperen, orig_bracket, edit_lks[i]);
                                }
                            }
                        }
                    } else if (conf.wgPageName.substr(0, 18) === 'User:COIBot/XWiki/') {
                        edit_lks = $('span.mw-editsection').toArray();
                        if (edit_lks.length === 0) {
                            return;
                        }
                        i = edit_lks.length - 1;
                        anchors = edit_lks[i].getElementsByTagName('a');
                        if (anchors != null && anchors.length > 0) {
                            anchor = anchors[0];
                            href   = anchor.getAttribute('href');
                            if (href.indexOf('&section=') > 0) {
                                orig_bracket = edit_lks[i].firstChild;
                                addRequestLinks('close', href + '&fakeaction=' + SBHandler.sb_close_na, orig_bracket, edit_lks[i]);
                                addRequestLinks('ignore', href + '&fakeaction=' + SBHandler.sb_close_ignore, orig_bracket, edit_lks[i]);
                                addRequestLinks('reverted', href + '&fakeaction=' + SBHandler.sb_close_rev, orig_bracket, edit_lks[i]);
                                addRequestLinks('add', href + '&fakeaction=' + SBHandler.sb_close_add, orig_bracket, edit_lks[i]);
                            }
                        }
                    } else if (conf.wgPageName.substr(0, 18) === 'User:COIBot/Local/') {
                        edit_lks = $('span.mw-editsection').toArray();
                        if (edit_lks.length === 0) {
                            return;
                        }
                        i = edit_lks.length - 1;
                        anchors = edit_lks[i].getElementsByTagName('a');
                        if (anchors != null && anchors.length > 0) {
                            anchor = anchors[0];
                            href   = anchor.getAttribute('href');
                            if (href.indexOf('&section=') > 0) {
                                orig_bracket = edit_lks[i].firstChild;
                                addRequestLinks('close', href + '&fakeaction=' + SBHandler.sb_close_na, orig_bracket, edit_lks[i]);
                                addRequestLinks('ignore', href + '&fakeaction=' + SBHandler.sb_close_ignore, orig_bracket, edit_lks[i]);
                                addRequestLinks('reverted', href + '&fakeaction=' + SBHandler.sb_close_rev, orig_bracket, edit_lks[i]);
                                addRequestLinks('add', href + '&fakeaction=' + SBHandler.sb_close_add, orig_bracket, edit_lks[i]);
                            }
                        }
                    }

                } else if (param != null) {
                    // We're on a request page
                    var summary = null;
                    action = null;
                    var text = document.editform.wpTextbox1;
                    urls = [];
                    var i, m, url;
                    var append;

                    //Only do anything if we're editing a section.
                    if (document.getElementsByName('wpSection') == null) {
                        return;
                    }

                    // Get URLs
                    if (conf.wgPageName == 'Wikipedia:Yêu_cầu_thay_đổi_danh_sách_đen_về_spam') {
						var reurl = /\{\{([Bb][Ll][Rr]equest[Rr]egex)\|(.*?)\}\}/g;	
                        m = text.value.match(reurl);
                        if (m != null) {	
                            for (i = 0; i < m.length; i++) {
                                url = m[i].substr(m[i].indexOf('|') + 1, m[i].length - m[i].indexOf('|') - 3); // Can't simply refer to the group
                                url = url.replace(/^regex\=/,'');
                                url = url.replace(/^link\=/,'');
                                urls.push(url);
                            }
                        } else {
	                        reurl = /\{\{([Bb][Ll][Rr]equest[Ll]ink)\|(.*?)\}\}/g;	
    	                    m = text.value.match(reurl);
        	                if (m != null) {	
            	                for (i = 0; i < m.length; i++) {
            		                url = m[i].substr(m[i].indexOf('|') + 1, m[i].length - m[i].indexOf('|') - 3); // Can't simply refer to the group
                    	            url = url.replace(/^link\=/,'');
                            	    url = url.replace(/^http:\/\/\:/,'');
                        	        url = url.replace(/\s/g, '');
                        	        url = url.replace(/\&/g, '\\&');
                    	            url = url.replace(/\//g,'\\/');
                	                url = url.replace(/\?/g,'\\?');	
            	                    url = '\\b' + url.replace(/\./g, '\\.') + '\\b'
        	                        url = url.replace(/\\\/\\b/g,'\\/');
    	                            url = url.replace(/\$\\b/,'$');                        	        
	                                urls.push(url);
                            	}
                        	} else {
		                        reurl = /\{\{([Ll]ink[Ss]ummary|[Ll]ink[Tt]rack|[Ll]ink\s[Tt]rack|[Ll]ink\s[Ss]ummary|[Ss]pam[Ll]ink)\|(.*?)\}\}/g;
    		                    m = text.value.match(reurl);
        		                if (m != null) {	
            		                for (i = 0; i < m.length; i++) {
                		                url = m[i].substr(m[i].indexOf('|') + 1, m[i].length - m[i].indexOf('|') - 3); // Can't simply refer to the group
                    		            urls.push('\\b' + url.replace(/\./g, '\\.') + '\\b');
                        		    }
        	                	}
                        	}
                        }                        
                        SBrequest = text.value.match(/^\=\=\=.*?\=\=\=$/m);
                        if (SBrequest && SBrequest.length > 0) {
                            SBrequest = SBrequest[0].substr(3, SBrequest[0].length - 6);
                        } else {
                            SBrequest = '';
                        }

                        if (urls === '' && SBrequest !== '') {
                            m = SBrequest.match(/(?:www\.|)[^\s]*?\.[a-zA-Z]{2,3}/g);
                            for (i = 0; i < m.length; i++) {
                                if (m[i].substr(0, 4) === 'www.') {
                                    urls.push('\\b' + m[i].substr(4).replace(/\./g, '\\.') + '\\b');
                                } else {
                                    urls.push('\\b' + m[i].replace(/\./g, '\\.') + '\\b');
                                }
                            }
                        }
                    } else if (conf.wgPageName.substr(0, 18) === 'User:COIBot/XWiki/') {
                        url = conf.wgPageName.substr(18);
                        urls.push('\\b' + url.replace(/\./g, '\\.') + '\\b');
                        SBrequest = conf.wgPageName;

                        // Close report
                        if (param == SBHandler.sb_close_add || param == SBHandler.sb_close_rev || param == SBHandler.sb_close_na) {
                        	//FIXME: use regex?
                            text.value = text.value.replace("{{LinkStatus|open}}", "{{LinkStatus|closed}}");
                            text.value = text.value.replace("{{LinkStatus|Open}}", "{{LinkStatus|closed}}");
                            text.value = text.value.replace("{{LinkStatus|stale}}", "{{LinkStatus|closed}}");
                            text.value = text.value.replace("{{LinkStatus|Stale}}", "{{LinkStatus|closed}}");
                        }
                    } else if (conf.wgPageName.substr(0, 18) === 'User:COIBot/Local/') {
                        SBrequest = conf.wgPageName;

                        // Close report
                        if (param == SBHandler.sb_close_rev || param === SBHandler.sb_close_na) {
                            //FIXME: use regex?
                            text.value = text.value.replace("|open}}", "|closed}}");
                            text.value = text.value.replace("|Open}}", "|closed}}");
                            text.value = text.value.replace("|stale}}", "|closed}}");
                            text.value = text.value.replace("|Stale}}", "|closed}}");
                        }
                        if (param == SBHandler.sb_close_ignore ) {
                            //FIXME: use regex?
                            text.value = text.value.replace("|open}}", "|ignored}}");
                            text.value = text.value.replace("|Open}}", "|ignored}}");
                            text.value = text.value.replace("|stale}}", "|ignored}}");
                            text.value = text.value.replace("|Stale}}", "|ignored}}");
                        }
                    }

                    var copyWarn = document.getElementById('editpage-copywarn');
                    copyWarn.innerHTML = copyWarn.innerHTML + '<div style=\"border: 1px solid; margin: 5px; padding: 5px;\"><h3>SBHandler</h3>\n<div id=\"SBdebug\"></div>';
                    SBdebug = document.getElementById('SBdebug');
                    if (param == SBHandler.sb_close_add) {
                        summary = SBHandler.close_add_summary;
						var matchregex = /\[\[[Uu]ser\:(.*?)[\|\]]/;
                    	var signeduser = text.value.match(matchregex); 
                    	if ((signeduser == null) | (conf.wgPageName.substr(0, 11) === 'User:COIBot')) {
	                    	append = (typeof SBHandlerAddComment !== 'undefined' ? SBHandlerAddComment : ':{{Added}} vào [[MediaWiki:Spam-blacklist]].   --~~~~');
                    	} else {
	                    	append = (typeof SBHandlerAddComment !== 'undefined' ? SBHandlerAddComment : ':{{rto|'+signeduser[1]+'}} {{Added}} vào [[MediaWiki:Spam-blacklist]].  --~~~~');
                    	}
                        action = SBHandler.sb_add;
                    } else if (param == SBHandler.sb_close_rem) {
                        summary = SBHandler.close_rem_summary;
						var matchregex = /\[\[[Uu]ser\:(.*?)[\|\]]/;
                    	var signeduser = text.value.match(matchregex); 
                    	if ((signeduser == null) | (conf.wgPageName.substr(0, 11) === 'User:COIBot')) {
	                        append = (typeof SBHandlerRemComment !== 'undefined' ? SBHandlerRemComment : ':{{Removed}} khỏi [[MediaWiki:Spam-blacklist]].   ~~~~');
                    	} else {
	                        append = (typeof SBHandlerRemComment !== 'undefined' ? SBHandlerRemComment : ':{{rto|'+signeduser[1]+'}} {{Removed}} khỏi [[MediaWiki:Spam-blacklist]].   ~~~~');
                    	}
                        action = SBHandler.sb_rem;
                    } else if (param == SBHandler.sb_close_na) {
                        summary = SBHandler.close_na_summary;
						var matchregex = /\[\[[Uu]ser\:(.*?)[\|\]]/;
                    	var signeduser = text.value.match(matchregex); 
                    	if ((signeduser == null) | (conf.wgPageName.substr(0, 11) === 'User:COIBot')) {
                        	append = (typeof SBHandlerCloseComment !== 'undefined' ? SBHandlerCloseComment : ':{{Closing}} ~~~~');
                    	} else {
                        	append = (typeof SBHandlerCloseComment !== 'undefined' ? SBHandlerCloseComment : ':{{rto|'+signeduser[1]+'}} {{Closing}} ~~~~');
                    	}
                    } else if (param == SBHandler.sb_close_ignore) {
                        summary = SBHandler.close_na_summary;
						var matchregex = /\[\[[Uu]ser\:(.*?)[\|\]]/;
                    	var signeduser = text.value.match(matchregex); 
                    	if ((signeduser == null) | (conf.wgPageName.substr(0, 11) === 'User:COIBot')) {
                        	append = (typeof SBHandlerCloseComment !== 'undefined' ? SBHandlerCloseComment : ':{{Ignored}}  --~~~~');
                    	} else {
                        	append = (typeof SBHandlerCloseComment !== 'undefined' ? SBHandlerCloseComment : ':{{rto|'+signeduser[1]+'}} {{Ignored}} ~~~~');
                    	}
                    } else if (param == SBHandler.sb_close_rev) {
                        summary = SBHandler.close_rev_summary;
						var matchregex = /\[\[[Uu]ser\:(.*?)[\|\]]/;
                    	var signeduser = text.value.match(matchregex); 
                    	if ((signeduser == null) | (conf.wgPageName.substr(0, 11) === 'User:COIBot')) {
                        	append = (typeof SBHandlerCloseComment !== 'undefined' ? SBHandlerCloseComment : ':{{Reverted}} ~~~~');
                    	} else {
                        	append = (typeof SBHandlerRevComment !== 'undefined' ? SBHandlerRevComment : ':{{rto|'+signeduser[1]+'}} {{Reverted}} ~~~~');
                    	}
                    } else if (param == SBHandler.sb_close_dec) {
                        summary = SBHandler.close_dec_summary;
						var matchregex = /\[\[[Uu]ser\:(.*?)[\|\]]/;
                    	var signeduser = text.value.match(matchregex); 
                    	if ((signeduser == null) | (conf.wgPageName.substr(0, 11) === 'User:COIBot')) {
                        	append = (typeof SBHandlerCloseComment !== 'undefined' ? SBHandlerCloseComment : ':{{Declined}} ~~~~');
                    	} else {
	                        append = (typeof SBHandlerDecComment !== 'undefined' ? SBHandlerDecComment : ':{{rto|'+signeduser[1]+'}} {{Declined}} ~~~~');
                    	}
                    } else if (param == SBHandler.sb_close_decperen) {
                        summary = SBHandler.close_dec_summary;
						var matchregex = /\[\[[Uu]ser\:(.*?)[\|\]]/;
                    	var signeduser = text.value.match(matchregex); 
                    	if ((signeduser == null) | (conf.wgPageName.substr(0, 11) === 'User:COIBot')) {
                        	append = (typeof SBHandlerCloseComment !== 'undefined' ? SBHandlerCloseComment : ':{{Declined}}, xem [[Talk:Spam blacklist/Recurring requests]].  ~~~~');
                    	} else {
	                        append = (typeof SBHandlerDecComment !== 'undefined' ? SBHandlerDecComment : ':{{rto|'+signeduser[1]+'}} {{Declined}}, xem [[Talk:Spam blacklist/Recurring requests]].  ~~~~');
                    	}
                    }
                    if (summary != null) {
                        if (wpAction == 'edit') {
                            SBUtils.setEditSummary(summary);
                            text.value += '\n' + append;
                        }
                        if (action != null && urls !== '') {
                            SBdebug.innerHTML += '<span style=\"font-weight:bold;\">Action: </span>' + action + ';<br />';
                            SBdebug.innerHTML += '<span style=\"font-weight:bold;\">Domains: </span>' + urls.join(', ') + ';<br />';
                            var editform = document.getElementById('editform');
                            editform.action += '&fakeaction=' + param;

                            // Remove save button
                            var wpSave = document.getElementById('wpSave');
                            wpSave.parentNode.removeChild(wpSave);

                            //Add save link:
                            wpSave = document.createElement('span');
                            wpSave.setAttribute('id', 'wpSave');
                            wpSave.innerHTML = '<a href=\"javascript:SBHandler.saveRequest()\">Lưu và sửa danh sách đen</a> ';

                            var wpPreview = document.getElementById('wpPreview');
                            wpPreview.parentNode.insertBefore(wpSave, wpPreview);
                        }
                        // Don't close the window to allow adding a comment.
                        if (text.scrollHeight > text.clientHeight) {
                            text.scrollTop = text.scrollHeight - text.clientHeight;
                        }
                        text.focus();
                    }
                }
            },

            saveRequest: function () {
                SBdebug.innerHTML += '<span style=\"font-weight:bold;\">Đang lưu yêu cầu…</span><br />';
                var summary = document.getElementById('wpSummary').value;
                var text = document.getElementById('wpTextbox1').value;
                var section = document.getElementsByName('wpSection')[0].value;
                var minor = document.getElementById('wpMinoredit');
                if (minor.checked) {
                    minor = '&minor=1';
                } else {
                    minor = '&notminor=1';
                }
                var watch = document.getElementById('wpWatchthis');
                if (watch.checked) {
                    watch = '&watchlist=watch';
                } else {
                    watch = '&watchlist=unwatch';
                }
                if (section !== '') {
                    section = '&section=' + encodeURIComponent(section);
                }
				var edittoken = mw.user.tokens.get('csrfToken');
				var query = 'format=xml';
                var params = 'action=edit&title=' + encodeURIComponent(conf.wgPageName) + '&summary=' + encodeURIComponent(summary) + '&text=' + encodeURIComponent(text) + section + minor + watch + '&token=' + encodeURIComponent(edittoken);
                SBHandler.postRequest(query, SBHandler.setLocation, params, true);
            },

            setLocation: function (request) {
                var xml = request.responseXML;
                var location = conf.wgServer + conf.wgScriptPath + '/index.php' +
                    '?title=Special:SpamBlacklist' +
                    '&action=' + action +
                    '&urls=' + urls.join('|') +
                    '&request=' + SBrequest;
                if (xml != null) {
                    var edits = xml.getElementsByTagName('edit');
                    if (edits.length === 0) {
                        SBdebug.innerHTML = '<div style=\"font-weight:bold;\">Việc lưu trang có thể đã thất bại. Vui lòng tự đóng yêu cầu của mình. ' +
                            'Sử dụng <a href="' + location +
                            '" title="Special:SpamBlacklist">Special:SpamBlacklist</a>' +
                            ' để thêm/loại bỏ các tên miền vào/khỏi danh sách đen.<br />Tham số:<br /><pre>' + params + '</pre><br />Phản hồi:<pre>' + request.responseText + '</pre></div>';
                        return;
                    }
                    var result = edits[0].getAttribute('result');
                    SBHandler.oldid = edits[0].getAttribute('newrevid');
                    if (result != 'Success') {
                        SBdebug.innerHTML = '<div style=\"font-weight:bold;\">Lưu trang thất bại. Vui lòng tự đóng yêu cầu của mình. ' +
                            'Sử dụng <a href="' + location +
                            '" title="Special:SpamBlacklist">Special:SpamBlacklist</a>' +
                            ' để thêm/loại bỏ các tên miền vào/khỏi danh sách đen.<br />Tham số:<br /><pre>' + params + '</pre><br />Phản hồi:<pre>' + request.responseText + '</pre></div>';
                        return;
                    } else {
                        window.location = location;
                    }
                } else {
                    SBdebug.innerHTML += '<div style=\"font-weight:bold;\">LỖI: ' + request.status + '<br /> Vui lòng tự đóng yêu cầu của mình. ' +
                        'Sử dụng <a href="' + location +
                        '" title="Special:SpamBlacklist">Special:SpamBlacklist</a>' +
                        ' để thêm/loại bỏ các tên miền vào/khỏi danh sách đen.<br />Tham số:<br /><pre>' + params + '</pre><br />Phản hồi:<pre>' + request.responseText + '</pre></div>';
                    return;
                }
            },

            /*------------------------------------------------------------------------------------------
            Add to blacklist.
            ------------------------------------------------------------------------------------------*/
            edittoken: '',
            text: '',
            request: '',
            urls: '',
            action: '',
            timestamp: '',
            oldid: '',
            custom: false,

            SBWrapper: function () {
                document.title = 'MediaWiki:Spam-blacklist';

                // Set header
                var header = document.getElementsByTagName('h1')[0];
                header.innerHTML = 'MediaWiki:Spam-blacklist';

                // Set content
                var content = document.getElementById('bodyContent');
                content.innerHTML = '<h3 id=\"siteSub\">Bách khoa toàn thư mở Wikipedia</h3>' +
                  '<p>Sử dụng công cụ này để thêm các tên miền vào <a href=\"//vi.wikipedia.org/wiki/MediaWiki:Spam-blacklist\" title=\"MediaWiki:Spam-blacklist\">MediaWiki:Spam-blacklist</a>, hoặc loại bỏ chúng, và ghi lại nhật trình thay đổi. Lưu ý rằng nó sẽ không thể vượt qua được các liên kết của chúng. <span style=\"font-weight:bold;\">Đừng sử dụng công cụ này trừ khi bạn có được kiến thức cơ bản về regex.</span> Bạn vẫn cần phải xác nhận thay đổi. Không bảo đảm rằng sửa đổi được yêu cầu là đúng.</p>';

                SBHandler.action = SBUtils.getParamValue('action');
                SBHandler.urls = SBUtils.getParamValue('urls');
                SBHandler.request = SBUtils.getParamValue('request');

                if ((SBHandler.action === 'add' || SBHandler.action === 'rem') && SBHandler.urls != null && SBHandler.urls !== '' && SBHandler.request != null) {
                    content.innerHTML += '<div id=\"SBstatus\" style=\"font-style: italic; border: 1px solid; padding: 5px; float:right;\">' +
                                        '<span id=\"Sthrobber\" style=\"text-align:center; font-weight:bold; float:right;\">' +
                                        '<img src=\"//upload.wikimedia.org/wikipedia/commons/d/d2/Spinning_wheel_throbber.gif\" alt=\"Đang tải\">' +
                                        'Đang tải…</span>' +
                                        '<br clear=\"all\" />' +
                                        '<table><tr style=\"vertical-align:top;\"><td>' +
                                        '<h5>Danh sách đen</h5>' +
                                        '<ul><li id=\"SgetBL\" style=\"color:grey;\">Nhận văn bản danh sách đen</li>' +
                                        '<li id=\"SaddBL\" style=\"color:grey;\">Thêm/loại bỏ tên miền</li>' +
                                        '<li id=\"SgetC\" style=\"color:grey;\">Nhận thay đổi từ máy chủ</li>' +
                                        '<li id=\"SparseBL\" style=\"color:grey;\">Phân tích và xem thay đổi</li>' +
                                        '<li id=\"SconfirmBL\" style=\"color:grey;\">Xác nhận thay đổi</li>' +
                                        '<li id=\"SsaveBL\" style=\"color:grey;\">Lưu thay đổi</li></ul></td><td>' +
                                        '<h5>Nhật trình</h5>' +
                                        '<ul><li id=\"SgetL\" style=\"color:grey;\">Nhận văn bản nhật trình</li>' +
                                        '<li id=\"SaddL\" style=\"color:grey;\">Thêm/loại bỏ tên miền</li>' +
                                        '<li id=\"SsaveL\" style=\"color:grey;\">Lưu thay đổi</li>' +
                                        '</ul></tr></table></div><br clear=\"all\" />' +
                                        '<h3>Danh sách đen</h3><div id=\"SBlist\"></div>' +
                                        '<h3>Nhật trình</h3><div id=\"SBlog\"></div>';
                    SBlist = document.getElementById("SBlist");
                    SBlog = document.getElementById("SBlog");
                    edittoken = mw.user.tokens.get('csrfToken');
                    SBHandler.getRequest('action=query&prop=info&titles=MediaWiki:Spam-blacklist&token=' + encodeURIComponent(edittoken), SBHandler.getBL, true);
                } else {
                    content.innerHTML += '<p style=\"font-style:italic\">Công cụ này chỉ có thể được sử dụng cùng với <a href=\"//vi.wikipedia.org/wiki/Wikipedia:Yêu_cầu_thay_đổi_danh_sách_đen_về_spam\" title=\"Wikipedia:Yêu cầu thay đổi danh sách đen về spam\">Wikipedia:Yêu cầu thay đổi danh sách đen về spam</a> để thêm hay loại bỏ các tên miền.</p>';
                }
            },

            // Get the current text and oldid of [[MediaWiki:Spam-blacklist]]
            getBL: function (request) {
                var xml = request.responseXML;
                if (xml != null) {
                    var pages = xml.getElementsByTagName('page');
                    SBHandler.edittoken = mw.user.tokens.get('csrfToken');
                    SBHandler.getRequest('action=query&prop=revisions&titles=MediaWiki:Spam-blacklist&rvprop=ids|timestamp|user|comment|content', SBHandler.parseBL, true);
                }
            },

            // Add/remove domains from the text
            parseBL: function (request) {
                var xml = request.responseXML;
                if (xml == null) {
                    SBlist.innerHTML += '<div style=\"font-weight:bold;\">LỖI: ' + request.status + '<br />Đang hủy bỏ.</div>';
                    return;
                }
                var revs = xml.getElementsByTagName('rev');
                SBHandler.timestamp = revs[0].getAttribute('timestamp');
                SBHandler.text = revs[0].textContent;
                var oldlength = SBHandler.text.length;
                document.getElementById('SgetBL').style.color = 'black';

                if (SBHandler.action == SBHandler.sb_add) {
                    urls = SBHandler.urls.replace(/\|/g, '\n');
                    if (SBHandler.text.length > 1000) {
                        var lastchars = SBHandler.text.substr(-1000);
                        SBHandler.text = SBHandler.text.substr(0, SBHandler.text.length - 1000);
                        if (lastchars.indexOf('## sbhandler_end') > 0) {
                            lastchars = lastchars.replace('## sbhandler_end', urls + '\n## sbhandler_end');
                        } else {
                            SBlist.innerHTML += '<div style=\"font-weight:bold;\">LỖI: Không thể tìm thấy điểm đánh dấu. Đang huỷ bỏ.</div>';
                            return;
                        }
                        SBHandler.text += lastchars;
                    } else {
                        if (SBHandler.text.indexOf('## sbhandler_end') > 0) {
                            SBHandler.text = SBHandler.text.replace('## sbhandler_end', urls + '\n## sbhandler_end');
                        } else {
                            SBlist.innerHTML += '<div style=\"font-weight:bold;\">LỖI: Không thể tìm thấy điểm đánh dấu. Vui lòng thêm \"## sbhandler_end\" vào dòng đơn dưới mục danh sách đen và thử lại.</div>';
                            return;
                        }
                    }
                } else if (SBHandler.action == SBHandler.sb_rem) {
                    urls = SBHandler.urls.split('|');
                    for (var i = 0; i < urls.length; i++) {
                        SBHandler.text = SBHandler.text.replace(urls[i] + '\n', '');
                    }
                }
                //Check if the length changed, if not assume nothing changed.
                if (oldlength == SBHandler.text.length) {
                    SBlist.innerHTML += '<div style=\"font-weight:bold;\">LỖI: Độ dài văn bản cũ và mới là như nhau. Điều này không nên xảy ra. Đang hủy bỏ.</div>';
                    return;
                }
                document.getElementById('SaddBL').style.color = 'black';
                params = 'action=query&prop=revisions&titles=MediaWiki:Spam-blacklist&rvdifftotext=' + encodeURIComponent(SBHandler.text);
                SBHandler.postRequest('format=xml', SBHandler.parseDiff, params, true);
            },

            // Parse and show the proposed edit
            parseDiff: function (request) {
                var xml = request.responseXML;
                if (xml != null) {
                    document.getElementById('SgetC').style.color = 'black';
                    var diffSource = xml.getElementsByTagName('diff');
                    var summary;
                    if (diffSource[0].childNodes[0].nodeValue) {
                        urls = SBHandler.urls.split('|');

                        if (SBHandler.action == 'add') {
                            summary = 'Đang thêm ';
                        } else {
                            summary = 'Đang loại bỏ ';
                        }

                        if (urls.length > 1) {
                            summary += urls.length + ' domains ';
                        } else {
                            summary += urls[0] + ' ';
                        }

                        if (SBHandler.request.substr(0, 18) == 'User:COIBot/XWiki/') {
                            summary += 'theo [[' + SBHandler.request + ']].';
                        } else {
                            summary += 'theo [[Wikipedia:Yêu cầu thay đổi danh sách đen về spam]].';
                        }

                        SBlist.innerHTML += '<div id="wikiDiff"><table class="diff"><col class="diff-marker" /><col class="diff-content" /><col class="diff-marker" /><col class="diff-content" /><tr valign="top"><td colspan="2" class="diff-otitle">Phiên bản hiện tại</td><td colspan="2" class="diff-ntitle">Nội dung của bạn</td></tr>' +
                          diffSource[0].childNodes[0].nodeValue + '</table></div>' +
                          '<br /><div id=\"BLform\">' +
                          '<input type=\"text\" value=\"' + summary + '\" id=\"summary\" maxlength=\"200\" size=\"60\" >&nbsp;&nbsp;&nbsp;<button onclick=\"SBHandler.submitBL()\">Xác nhận thay đổi</button><button onclick=\"SBHandler.editBL()\">Sửa thay đổi</button></div>';

                        document.getElementById('SparseBL').style.color = 'black';
                    } else {
                        SBlist.innerHTML += '<div style=\"font-weight:bold;\">LỖI: Không thể hiển thị thay đổi.<br />Đang hủy bỏ.</div>';
                        return;
                    }
                } else {
                    SBlist.innerHTML += '<div style=\"font-weight:bold;\">LỖI: ' + request.status + '<br />Đang hủy bỏ.</div>';
                    return;
                }
            },

            // Add a text area to change the blacklist yourself

            editBL: function () {
                var BLform = document.getElementById('BLform');
                BLform.innerHTML = '<textarea name=\"wpTextbox1\" id=\"wpTextbox1\" cols=\"80\" rows=\"25\" accesskey=\",\">' +
                  SBHandler.text +
                  '</textarea>' +
                  BLform.innerHTML;
            },

            // Submit the edit to [[Spam blacklist]]
            submitBL: function () {
                var wpTextbox = document.getElementById('wpTextbox1');
                if (wpTextbox != null) {
                    SBHandler.text = wpTextbox.value;
                    SBHandler.custom = true; //We can't simply log the change. User needs to do that.
                }
                document.getElementById('SconfirmBL').style.color = 'black';
                summary = document.getElementById('summary').value; // note that this sets a global var, should not be locally defined!
                summary += ' Sử dụng [[:w:vi:Thành viên:NgocAnMaster/Gadget-SBHandler.js|Thành viên:NgocAnMaster/Gadget-SBHandler.js]].';
                var query = 'format=xml';
                params = 'action=edit&title=MediaWiki:Spam-blacklist&summary=' + encodeURIComponent(summary) + '&text=' + encodeURIComponent(SBHandler.text) + '&basetimestamp=' + SBHandler.timestamp  +  '&token=' + encodeURIComponent(SBHandler.edittoken);
                SBHandler.postRequest(query, SBHandler.LWrapper, params, true);
            },

            // Start logging procedure
            LWrapper: function (request) {
                var xml = request.responseXML;
                if (xml != null) {
                    var edits = xml.getElementsByTagName('edit');
                    if (edits.length === 0) {
                        SBlist.innerHTML = '<div style=\"font-weight:bold;\">Việc lưu trang có thể đã thất bại. Vui lòng kiểm tra xem nó đã thành công hay chưa và tự ghi nhật trình sửa đổi nếu cần.</div>';
                        return;
                    }
                    var result = edits[0].getAttribute('result');
                    SBHandler.oldid = edits[0].getAttribute('newrevid');
                    if (result !== 'Success') {
                        SBlist.innerHTML = '<div style=\"font-weight:bold;\">Lưu trang thất bại. Vui lòng tự đưa tên miền vào danh sách đen.</div>';
                        return;
                    } else {
                        document.getElementById('SsaveBL').style.color = 'black';
                        SBlist.innerHTML = '<div>Danh sách đen đã được cập nhật, <a href=\"' + conf.wgServer + conf.wgScriptPath + '/index.php?oldid=' + SBHandler.oldid + '&diff=prev\" title=\"Thay đổi\">xem thay đổi</a>.</div>';
                    }

                } else {
                    SBlist.innerHTML += '<div style=\"font-weight:bold;\">LỖI: ' + request.status + '<br />Đang hủy bỏ.</div>';
                    return;
                }

                var d = new Date();
                var m = d.getMonth() + 1;
                if (m < 10) {
                    m = '0' + m;
                }
                var y = d.getFullYear();
                logtitle = 'Spam blacklist/Log/' + y + '/' + m;

                if (SBHandler.request.substr(0, 18) != 'User:COIBot/XWiki/') {
                    SBHandler.getRequest('action=query&prop=revisions&titles=Wikipedia:Yêu cầu thay đổi danh sách đen về spam&rvprop=ids|timestamp|user|comment|content', SBHandler.parseTBL, true);
                } else {
                    SBHandler.getRequest('action=query&prop=revisions&titles=' + logtitle + '&rvprop=ids|timestamp|user|comment|content', SBHandler.parseL, true);
                }
            },

            // Get current oldid of [[Talk:Spam blacklist]], because that's the location of the request.
            parseTBL: function (request) {
                var xml = request.responseXML;
                if (xml != null) {
                    var revs = xml.getElementsByTagName('rev');
                    tprevid = revs[0].getAttribute('revid');
                } else {
                    SBlog.innerHTML += '<div style=\"font-weight:bold;\">LỖI: ' + request.status + '<br />. Vui lòng tự ghi nhật trình sửa đổi.</div>';
                    return;
                }

                SBHandler.getRequest('action=query&prop=revisions&titles=' + logtitle + '&rvprop=ids|timestamp|user|comment|content', SBHandler.parseL, true);
            },

            // Add/remove domains to/from log
            parseL: function (request) {
                var xml = request.responseXML;
                if (xml != null) {
                    document.getElementById('SgetL').style.color = 'black';
                    var revs = xml.getElementsByTagName('rev');
                    if (revs.length === 0) {
                        SBlog.innerHTML += '<div style=\"font-weight:bold;\">LỖI: Không thể nhận nhật trình.<br /> Nó có thể chưa tồn tại. Vui lòng tạo <a href="//vi.wikipedia.org/wiki/' + logtitle + '" title="' + logtitle + '">' + logtitle + '</a> và tự ghi nhật trình sửa đổi.</div>';
                        return;
                    }
                    SBHandler.timestamp = revs[0].getAttribute('timestamp');
                    SBHandler.text = revs[0].textContent;
                } else {
                    SBlog.innerHTML += '<div style=\"font-weight:bold;\">LỖI: ' + request.status + '<br /> Vui lòng tự ghi nhật trình sửa đổi.</div>';
                    return;
                }

                var sbldiff;
                if (SBHandler.action == SBHandler.sb_add) {
                    sbldiff = '{{sbl-diff|' + SBHandler.oldid + '}}';
                } else {
                    sbldiff = '{{sbl-diff|' + SBHandler.oldid + '|removal}}';
                }

                urls = SBHandler.urls.split('|');
                var r = SBHandler.request;
                if (r.substr(0, 18) === 'User:COIBot/XWiki/') {
                    r = '[[' + r + ']]';
                } else {
                    r = '{{sbl-log|' + tprevid + '#{{subst:anchorencode:' + r + '}}}}';
                }

                var spaces = '                                        ';

                if (urls.length == 1) {
                    log_text = ' ' + urls[0] + spaces.substr(0, 39 - urls[0].length) + '# ' +
                      conf.wgUserName + ' # ' + sbldiff + '; see ' + r;
                } else {
                    log_text = ' #:                                     ' +
                      conf.wgUserName + ' # ' + sbldiff + '; see ' + r;
                    for (var i = 0; i < urls.length; i++) {
                        log_text += '\n   ' + urls[i];
                    }
                }

                // User needs to confirm log edit
                if (SBHandler.custom) {
                    SBlog.innerHTML += '<p>Nội dung sau sẽ được thêm vào nhật trình. Bạn cần cập nhật thông tin này để nó phản ánh những thay đổi mà bạn đã thực hiện đối với đề nghị sửa đổi.</p>' +
                      '<textarea name=\"wpTextbox1\" id=\"wpTextbox1\" cols=\"80\" rows=\"10\" accesskey=\",\">' +
                      log_text +
                      '</textarea>' +
                      '<button onclick=\"SBHandler.submitL()\">Xác nhận thay đổi</button>';
                } else {
                    SBHandler.submitL();
                }
            },

            submitL: function () {
                var wpTextbox = document.getElementById('wpTextbox1');
                if (wpTextbox != null) {
                    SBHandler.text += '\n' + wpTextbox.value;
                } else {
                    SBHandler.text += '\n' + log_text;
                }
                document.getElementById('SaddL').style.color = 'black';
                var query = 'format=xml';
                var params = 'action=edit&title=' + encodeURIComponent(logtitle) + '&summary=' + encodeURIComponent(summary) + '&text=' + encodeURIComponent(SBHandler.text) + '&token=' + encodeURIComponent(SBHandler.edittoken);
                SBHandler.postRequest(query, SBHandler.LEnd, params, true);
            },

            // Confirm results
            LEnd: function (request) {
                var xml = request.responseXML;

                if (xml != null) {
                    var edits = xml.getElementsByTagName('edit');
                    if (edits.length === 0) {
                        SBlist.innerHTML = '<div style=\"font-weight:bold;\">Việc lưu trang có thể đã thất bại. Vui lòng kiểm tra xem nó đã thành công hay chưa và tự ghi nhật trình sửa đổi nếu cần.</div>';
                        return;
                    }
                    var result = edits[0].getAttribute('result');
                    var oldid = edits[0].getAttribute('newrevid');
                    if (result !== 'Success') {
                        SBlog.innerHTML = '<div>Lưu trang thất bại. Vui lòng tự ghi nhật trình sửa đổi.</div>';
                        return;
                    } else {
                        document.getElementById('SsaveL').style.color = 'black';
                        document.getElementById('Sthrobber').innerHTML = '';
                        SBlog.innerHTML = '<div>Nhật trình đã được cập nhật, <a href=\"' + conf.wgServer + conf.wgScriptPath + '/index.php?oldid=' + oldid + '&diff=prev\" title=\"Thay đổi\">xem thay đổi</a>.<p style=\"font-style:italic\">Cảm ơn vì đã hỗ trợ Danh sách đen về spam! Quay lại <a href=\"//vi.wikipedia.org/wiki/Wikipedia:Yêu_cầu_thay_đổi_danh_sách_đen_về_spam\" title=\"Wikipedia:Yêu cầu thay đổi danh sách đen về spam\">Wikipedia:Yêu cầu thay đổi danh sách đen về spam</a>.</p></div>';
                    }
                }
            },

            getRequest: function (query, callback, api) {
                var url;
                if (api) {
                    url = conf.wgServer + conf.wgScriptPath + '/api.php?format=xml&' + query;
                } else {
                    url = conf.wgServer + conf.wgScriptPath + '/index.php?' + query;
                }

                $.ajax({
                    url: url,
                    type: 'GET',
                    headers: {
                        'Pragma': 'cache=yes',
                        'Cache-Control': 'no-transform'
                    }
                }).done(function (data, textStatus, jqXHR) {
                    callback(jqXHR);
                });
            },

            postRequest: function (query, callback, params, api) {
                var url;
                if (api) {
                    url = conf.wgServer + conf.wgScriptPath + '/api.php?' + query;
                } else {
                    url = conf.wgServer + conf.wgScriptPath + '/index.php?' + query;
                }

                $.ajax({
                    url: url,
                    type: 'POST',
                    headers: {
                        'Content-type': 'application/x-www-form-urlencoded',
                        'Content-length': params.length,
                        'Pragma': 'cache=yes',
                        'Cache-Control': 'no-transform'
                    },
                    data: params
                }).done(function (data, textStatus, jqXHR) {
                    callback(jqXHR);
                });
            },

            setupHandler: function () {
                if (conf.wgPageName == 'Special:SpamBlacklist') {
                    SBHandler.SBWrapper();
                } else {
                    SBHandler.closeRequestLinks();
                }
            }

        };
        // End of SBHandler object

        $(SBHandler.setupHandler);

    }
    // End of if-sysop check

    // Export global variables
    window.SBHandler = SBHandler;
    window.SBrequest = SBrequest;

}());
// </nowiki>
// [[Category:Gadgets|SBHandler.js]]