Interested Article - Gadget-featuredlists.js

После сохранения или недавних изменений очистите кэш браузера .
Возможно, этот код документирован .

/* <nowiki>
 * Скрипт для [[ВП:КИСП]]
 * Инструкция — на [[Википедия:Гаджеты/Гаджет проекта «Избранные списки и порталы»]]
 * За основу взяты [[У:Claymore/goodarticles.js]] и [[У:Serpent Vlad/featuredarticles.js]], 
 [[У:NoFrost/featuredlists.js]]
 * Лицензия: GNU GPL
 * Авторы: Claymore, Serpent Vlad, Saint Johann, NoFrost
 */

if( typeof( wfAnchorEncode ) != "function" ) {
	function wfAnchorEncode(str) {
		str = encodeURIComponent( str );
		str = str.replace( /%/g, "." );
		str = str.replace( /\.20/g, "_" );
		str = str.replace( /\.3A/g, ":" );
		return str;
	}
}

function ch( o ) { for( var i in o ) { return o[i] } }

function replTitle(regex) {
	var title = mw.config.get('wgPageName').replace( /\_/g, " " );
	if(regex){
		title = title.replace( /\(/g, "\\(" );
		title = title.replace( /\)/g, "\\)" );
		title = title.replace( /\,/g, "\\," );
		title = title.replace( /\-/g, "\\-" );
		title = title.replace( /\—/g, "\\—" );
		title = title.replace( /\«/g, "\\«" );
		title = title.replace( /\»/g, "\\»" );
	}
	return title;
}

function isOfficer() {
	// список избирающих проекта Избранные списки и порталы загружается из [[MediaWiki:Gadget-featuredlists.json]]
	var officerList = require( './featuredlists.json' );
	return officerList.includes( mw.config.get( 'wgUserName' ) );
}

function sendError( textError ) {
	var sectiontext = "== Ошибка скрипта ==";
	var talktext = "При избрании страницы [[" + replTitle() + "]] [[MediaWiki:Gadget-featuredlists.js|скрипт]] не сработал из-за следующей ошибки: " + textError + ". ~~\~~\n";
	
	var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=edit&title=' + encodeURIComponent( 'Обсуждение MediaWiki:Gadget-featuredlists.js' );
		var rq = "summary=" + encodeURIComponent( 'Сообщение об ошибке в работе скрипта избрания КИСП' ) +
							"&section=" + encodeURIComponent( 'new' ) +
							"&sectiontitle=" + encodeURIComponent( sectiontext ) +
							"&text=" + encodeURIComponent( talktext ) +
							"&token=" + encodeURIComponent( wgMakeFLP.edittoken );

		wgMakeFLP.rq.onreadystatechange = wgMakeFLP.onNominationFalse;
		wgMakeFLP.rq.open( "POST", uri, true );
		wgMakeFLP.rq.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
		wgMakeFLP.rq.send( rq );
}
	
var wgMakeFLP = {
	'rq' : null,
	'newtext' : '',
	'talktext' : '',
	'editsummary' : '',
	'edittoken' : '',
	'date' : '',
	'isPortal' : false,
	'months' : {
		'0' : 'Январь',
		'1' : 'Февраль',
		'2' : 'Март',
		'3' : 'Апрель',
		'4' : 'Май',
		'5' : 'Июнь',
		'6' : 'Июль',
		'7' : 'Август',
		'8' : 'Сентябрь',
		'9' : 'Октябрь',
		'10' : 'Ноябрь',
		'11' : 'Декабрь'
	},
	'months_to' : {
		'0' : 'января',
		'1' : 'февраля',
		'2' : 'марта',
		'3' : 'апреля',
		'4' : 'мая',
		'5' : 'июня',
		'6' : 'июля',
		'7' : 'августа',
		'8' : 'сентября',
		'9' : 'октября',
		'10' : 'ноября',
		'11' : 'декабря'
	},
	summarySuffix : '(с помощью [[MediaWiki:Gadget-featuredlists.js|Гаджета проекта «Избранные списки и порталы»]])',

	'addMakeFeaturedTab' : function() {
		if( !document.getElementById( 'mw-indicator-fl-candidate' ) ) return;

		mw.loader.using('mediawiki.util').done( function() {
			mw.util.addPortletLink( 'p-cactions', 'javascript:wgMakeFLP.makeFeatured()',
									'Избрать ИСП', 'ca-make-flp', 'Сделать список или портал избранным' );
		} );
	},

	'onTextDownload' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;

		result = eval('('+this.responseText+')');
		var pgtext = ch(result.query.pages).revisions[0]['*'];
		var nominationRegex = /\{{2}Кандидат в избранные списки и порталы\|(\d{4})-(\d{2})-(\d{2})\}{2}/i;
		if (!pgtext.match(nominationRegex)) {
			alert('Редактирование невозможно: нет даты (либо она неверно указана) в шаблоне кандидата в избранные списки или порталы (смотрите руководство к скрипту)'); 
			sendError('нет даты (либо она неверно указана) в шаблоне кандидата в избранные списки или порталы (смотрите руководство к скрипту) — в <onTextDownload>');
			return;
		}
		var match = pgtext.match( nominationRegex );
		wgMakeFLP.date = match[1] + '-' + match[2] + '-' + match[3];
		wgMakeFLP.isPortal = ( mw.config.get('wgNamespaceNumber') === 100 ? true : false );
		wgMakeFLP.newtext = pgtext.replace( nominationRegex, '{{Избранный список или портал|тип=' + ( wgMakeFLP.isPortal ? 'портал' : 'список' ) + '}}' );
		var today = '{{' + 'subst:CURRENTDAY}} {{' + 'subst:CURRENTMONTHNAMEGEN}} {{' + 'subst:CURRENTYEAR}}';
		
		wgMakeFLP.talktext = '{{Сообщение ' + ( wgMakeFLP.isPortal ? 'ИП' : 'ИСП') + '|' + wgMakeFLP.date + '|' + today + '|' + replTitle() + '}}\n';
		wgMakeFLP.editsummary = (wgMakeFLP.isPortal ? "Портал" : "Список") + " [[" + replTitle() + "]] [[ВП:ИСП|избран]] " + wgMakeFLP.summarySuffix;
		
		var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=query&prop=info&meta=tokens&type=csrf&titles=' + encodeURIComponent( mw.config.get('wgPageName') );
		wgMakeFLP.rq.onreadystatechange = wgMakeFLP.onTokenDownload;
		wgMakeFLP.rq.open( "GET", uri, true );
		wgMakeFLP.rq.send( "" );
	},

	'onTokenDownload' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;

		result = eval('('+this.responseText+')');
		wgMakeFLP.edittoken = result.query.tokens.csrftoken;
		if( !wgMakeFLP.edittoken ) {
			alert( 'Редактирование невозможно – не могу получить токен!' );
			sendError('не могу получить токен');
			return;
		} else {
			alert('Токен получен...');
		}

		var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=edit&title=' + encodeURIComponent( mw.config.get('wgPageName') );
		var rq = "summary=" + encodeURIComponent( wgMakeFLP.editsummary ) +
							"&text=" + encodeURIComponent( wgMakeFLP.newtext ) +
							"&token=" + encodeURIComponent( wgMakeFLP.edittoken );

		wgMakeFLP.rq.onreadystatechange = wgMakeFLP.onEditSaved;
		wgMakeFLP.rq.open( "POST", uri, true );
		wgMakeFLP.rq.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
		wgMakeFLP.rq.send( rq );
	},

	'onEditSaved' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;

		result = eval('('+this.responseText+')');
		if( typeof( result.error ) != 'undefined' ) {
			alert( "Не удалось сохранить страницу: " + result.error.info );
			sendError(result.error.info + ' — в <onEditSaved>');
			return;
		} else {
			alert('Страница ' + mw.config.get('wgPageName') + ' обновлена...');
		}

		var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=edit&title=' + encodeURIComponent( 'Обсуждение' + (wgMakeFLP.isPortal ? ' портала': '') + ':' + mw.config.get('wgPageName') );
		var rq = "summary=" + encodeURIComponent( wgMakeFLP.editsummary ) +
							"&prependtext=" + encodeURIComponent( wgMakeFLP.talktext ) +
							"&token=" + encodeURIComponent( wgMakeFLP.edittoken );

		wgMakeFLP.rq.onreadystatechange = wgMakeFLP.onNominationSaved;
		wgMakeFLP.rq.open( "POST", uri, true );
		wgMakeFLP.rq.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
		wgMakeFLP.rq.send( rq );  
	},

	'onNominationSaved' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;

		result = eval('('+this.responseText+')');
		if( typeof( result.error ) != 'undefined' ) {
			alert( "Не удалось сохранить страницу: " + result.error.info );
			sendError(result.error.info + ' — в <onNominationSaved>');
			return;
		} else {
			alert('Страница обсуждения страницы ' + mw.config.get('wgPageName') + ' обновлена...');
		}

		var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=query&prop=revisions&rvprop=content&rvlimit=1&titles=' +
							encodeURIComponent( 'Википедия:Кандидаты_в_избранные_списки_и_порталы' );
		wgMakeFLP.rq.onreadystatechange = wgMakeFLP.onLogDownload;
		wgMakeFLP.rq.open( "GET", uri, true );
		wgMakeFLP.rq.send( "" );  
	},

	'onLogDownload' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;

		result = eval('('+this.responseText+')');
		var pgtext = ch(result.query.pages).revisions[0]['*'];
		var nominationRegex = "\\|-(?: {0,})\\n(?:\\|(?: {0,})(?:rowspan=\"?(?:\\d+)\"?(?: {0,})\\|(?: {0,}))?\\[{2}(?:Википедия|ВП):Кандидаты в избранные списки и порталы\\/" + wgMakeFLP.date + "\\|\\d{1,2} [а-я]+\\]{2}(?: {0,})\\n)?\\|(?: {0,})\\[{2}" + replTitle(true) + "\\]{2}(?: {0,})\\n\\|(?: {0,})(?:.*)(?: {0,})\\n\\|(?: {0,})(.*)(?: {0,})";
		
		if (!pgtext.match(nominationRegex)) {
			alert('Редактирование невозможно: не найдена запрашиваемая строка в статье <Википедия:Кандидаты в избранные списки и порталы>');
			sendError('не найдена запрашиваемая строка в статье [[Википедия:Кандидаты в избранные списки и порталы]]');
			return;
		}
		var match = pgtext.match( nominationRegex );
	
		var allText = match[0];
		var endText = match[1];
		
		var text = allText.replace( '|-', '|- style="background-color:gold;"');
		text = text.replace( endText, ( wgMakeFLP.isPortal ? "Портал" : "Список" ) + ' избран' );
			
		wgMakeFLP.newtext = pgtext.replace( allText, text);
		wgMakeFLP.editsummary = ( wgMakeFLP.isPortal ? "Портал" : "Список" ) + " [[" + replTitle() + "]] избран " + wgMakeFLP.summarySuffix;
		
		var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=edit&title=' +
							encodeURIComponent( 'Википедия:Кандидаты_в_избранные_списки_и_порталы' );
		var rq = "summary=" + encodeURIComponent( wgMakeFLP.editsummary ) +
							"&text=" + encodeURIComponent( wgMakeFLP.newtext ) +
							"&token=" + encodeURIComponent( wgMakeFLP.edittoken );

		wgMakeFLP.rq.onreadystatechange = wgMakeFLP.onLogSaved;
		wgMakeFLP.rq.open( "POST", uri, true );
		wgMakeFLP.rq.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
		wgMakeFLP.rq.send( rq );
	},

	'onLogSaved' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;

		result = eval('('+this.responseText+')');
		if( typeof( result.error ) != 'undefined' ) {
			alert( "Не удалось сохранить страницу: " + result.error.info );
			sendError(result.error.info + ' — в <onLogSaved>');
			return;
		} else {
			alert('Страница <Википедия:Кандидаты в избранные списки и порталы> обновлена...');
		}

		var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=query&prop=revisions&rvprop=content&rvlimit=1&titles=' +
							encodeURIComponent( 'Википедия:Избранные_списки_и_порталы/Журнал_избраний' );
		wgMakeFLP.rq.onreadystatechange = wgMakeFLP.onLogDownloadTwo;
		wgMakeFLP.rq.open( "GET", uri, true );
		wgMakeFLP.rq.send( "" );
	},
	
	'onLogDownloadTwo' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;
			
		result = eval('('+this.responseText+')');
		var pgtext = ch(result.query.pages).revisions[0]['*'];
		var nominationRegex = "={2} Избранные " + ( wgMakeFLP.isPortal ? "порталы": "списки" ) + " ={2}(?: {0,})\\n<!\\-\\- (?:.*) \\-\\->\\n<onlyinclude>(?:.*)\\|(?: {0,})\\n";
		
		if (!pgtext.match(nominationRegex)) {
			alert('Редактирование невозможно: не найдена запрашиваемая строка в статье <Избранные списки и порталы/Журнал избраний>');
			sendError('не найдена запрашиваемая строка в статье [[Википедия:Избранные списки и порталы/Журнал избраний]]');
			return;
		}
		var match = pgtext.match( nominationRegex );
	
		var newText = "\n# [[" + replTitle() + "]] избран. [[У:{{" + "subst:REVISIONUSER}}|{{" + "subst:REVISIONUSER}}]] ~" + "~~" + "~~\n";
	
		wgMakeFLP.newtext = pgtext.replace(match[0],match[0] + newText);
		wgMakeFLP.editsummary = ( wgMakeFLP.isPortal ? "Портал" : "Список" ) + " [[" + replTitle() + "]] избран "+ wgMakeFLP.summarySuffix;
	
		var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=edit&title=' +
							encodeURIComponent( 'Википедия:Избранные_списки_и_порталы/Журнал_избраний' );
		var rq = "summary=" + encodeURIComponent( wgMakeFLP.editsummary ) +
							"&text=" + encodeURIComponent( wgMakeFLP.newtext ) +
							"&token=" + encodeURIComponent( wgMakeFLP.edittoken );

		wgMakeFLP.rq.onreadystatechange = wgMakeFLP.onListDownload;
		wgMakeFLP.rq.open( "POST", uri, true );
		wgMakeFLP.rq.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
		wgMakeFLP.rq.send( rq );
	},

	'onListDownload' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;

		result = eval('('+this.responseText+')');
		if( typeof( result.error ) != 'undefined' ) {
			alert( "Не удалось сохранить страницу: " + result.error.info );
			sendError(result.error.info + ' — в <onListDownload>');
			return;
		} else {
			alert('Страница <Википедия:Избранные списки и порталы/Журнал избраний> обновлена...');
		}
	
	var now = new Date();
	nowYear = now.getFullYear();
	nowMonth = now.getMonth();
	
	var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=query&prop=revisions&rvprop=content&rvlimit=1&titles=' +
							encodeURIComponent( 'Википедия:Кандидаты_в_избранные_списки_и_порталы/Архив/' + wgMakeFLP.months[nowMonth] + '_' + nowYear );   
		wgMakeFLP.rq.onreadystatechange = wgMakeFLP.arxivDownload;
		wgMakeFLP.rq.open( "GET", uri, true );
		wgMakeFLP.rq.send( "" );
	},

	'arxivDownload' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;

		result = eval('('+this.responseText+')');
		var pgtext = ch(result.query.pages).revisions[0]['*'];
	
	var date = wgMakeFLP.date.split('-');
	var nominationDate = date[2] + ' ' + wgMakeFLP.months_to[date[1] - 1];
		var today = '{{' + 'subst:CURRENTDAY}} {{' + 'subst:CURRENTMONTHNAMEGEN}} {{' + 'subst:CURRENTYEAR}}';
		var reText = '|- style="background-color:gold;"\n| [[Википедия:Кандидаты в избранные списки и порталы/' + wgMakeFLP.date + '|' + nominationDate + ']]\n| [[' + replTitle() + ']]\n| Статус присвоен ' + today + ' года\n|}';
	
		wgMakeFLP.newtext = pgtext.replace( '|}', reText );
		wgMakeFLP.editsummary = (wgMakeFLP.isPortal ? "Портал": "Список") + " [[" + replTitle() + "]] [[ВП:ИСП|избран]] " + wgMakeFLP.summarySuffix;
	
		var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=edit&title=' +
							encodeURIComponent( 'Википедия:Кандидаты_в_избранные_списки_и_порталы/Архив/' + wgMakeFLP.months[nowMonth] + '_' + nowYear );
		var rq = "summary=" + encodeURIComponent( wgMakeFLP.editsummary ) +
							"&text=" + encodeURIComponent( wgMakeFLP.newtext ) +
							"&token=" + encodeURIComponent( wgMakeFLP.edittoken );

		wgMakeFLP.rq.onreadystatechange = wgMakeFLP.onArxivDownload;
		wgMakeFLP.rq.open( "POST", uri, true );
		wgMakeFLP.rq.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
		wgMakeFLP.rq.send( rq );  
	},

	'onArxivDownload' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;

		result = eval('('+this.responseText+')');
		if( typeof( result.error ) != 'undefined' ) {
			alert( "Не удалось сохранить страницу: " + result.error.info );
			sendError(result.error.info + ' — в <onArxivDownload>');
			return;
		} else {
			mw.notify('Страница архива обновлена...');
		}

	mw.notify( 'Страница успешно избрана. <a href="javascript:location.reload()">Перезагрузить страницу</a>' );
	},

	'onNominationFalse' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;

		result = eval('('+this.responseText+')');
		if( typeof( result.error ) != 'undefined' ) {
			alert( "Не удалось сохранить страницу: " + result.error.info );
			return;
		}   

	mw.notify( '<b>Страница не избрана!</b> Подробности смотрите на [[Обсуждение MediaWiki:Gadget-featuredlists.js|на этой странице]]. <a href="javascript:location.reload()">Перезагрузить страницу</a>' );
	},
	
	'makeFeatured' : function() {
		var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=query&prop=revisions&rvprop=content&rvlimit=1&titles=' + encodeURIComponent( mw.config.get('wgPageName') );
		this.rq = new XMLHttpRequest();
		this.rq.onreadystatechange = this.onTextDownload;
		this.rq.open( "GET", uri, true );
		this.rq.send( "" );
	}
}


var wgDenyFLP = {
	'rq' : null,
	'newtext' : '',
	'talktext' : '',
	'editsummary' : '',
	'edittoken' : '',
	'date' : '',
	'isPortal': false,
	'months' : {
		'0' : 'Январь',
		'1' : 'Февраль',
		'2' : 'Март',
		'3' : 'Апрель',
		'4' : 'Май',
		'5' : 'Июнь',
		'6' : 'Июль',
		'7' : 'Август',
		'8' : 'Сентябрь',
		'9' : 'Октябрь',
		'10' : 'Ноябрь',
		'11' : 'Декабрь'
	},
	'months_to' : {
		'0' : 'января',
		'1' : 'февраля',
		'2' : 'марта',
		'3' : 'апреля',
		'4' : 'мая',
		'5' : 'июня',
		'6' : 'июля',
		'7' : 'августа',
		'8' : 'сентября',
		'9' : 'октября',
		'10' : 'ноября',
		'11' : 'декабря'
	},

	'addDenyTab' : function() {
		if( !document.getElementById( 'mw-indicator-fl-candidate' ) ) return;

		mw.loader.using('mediawiki.util').done( function() {
			mw.util.addPortletLink( 'p-cactions', 'javascript:wgDenyFLP.deny()',
									'Отказать ИСП', 'ca-deny-flp', 'Отказать в статусе избранного списка или портала' );
		} );
	},

	'onTextDownload' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;

		result = eval('('+this.responseText+')');
		var pgtext = ch(result.query.pages).revisions[0]['*'];
		var nominationRegex = /\{{2}Кандидат в избранные списки и порталы\|(\d{4})-(\d{2})-(\d{2})\}{2}/i;
		if (!pgtext.match(nominationRegex)) {
			alert('Редактирование невозможно: нет даты (либо она неверно указана) в шаблоне кандидата в избранные списки или порталы (смотрите руководство к скрипту)'); 
			sendError('нет даты (либо она неверно указана) в шаблоне кандидата в избранные списки или портала (смотрите руководство к скрипту)');
			return;
		}
		var match = pgtext.match( nominationRegex );
		wgDenyFLP.date = match[1] + '-' + match[2] + '-' + match[3];
		wgDenyFLP.isPortal = ( mw.config.get('wgNamespaceNumber') === 100 ? true : false );
		wgDenyFLP.newtext = pgtext.replace( nominationRegex, '' );
		var today = '{{' + 'subst:CURRENTDAY}} {{' + 'subst:CURRENTMONTHNAMEGEN}} {{' + 'subst:CURRENTYEAR}}';
		
		wgDenyFLP.talktext = '{{Сообщение ' + ( wgDenyFLP.isPortal ? 'ИП' : 'ИСП') + '|' + wgDenyFLP.date + '|' + today + '|Кандидат}}\n';
	wgDenyFLP.editsummary = ( wgDenyFLP.isPortal ? "Портал" : "Список" ) + " [[" + replTitle() + "]] отправлен на доработку [[ВП:ИСП]] " + wgMakeFLP.summarySuffix;
		
	var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=query&prop=info&meta=tokens&type=csrf&titles=' + encodeURIComponent( mw.config.get('wgPageName') );
		wgDenyFLP.rq.onreadystatechange = wgDenyFLP.onTokenDownload;
		wgDenyFLP.rq.open( "GET", uri, true );
		wgDenyFLP.rq.send( "" );
	},

	'onTokenDownload' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;

		result = eval('('+this.responseText+')');
		wgDenyFLP.edittoken = result.query.tokens.csrftoken;
		if( !wgDenyFLP.edittoken ) {
			alert( 'Редактирование невозможно – не могу получить токен!' );
			sendError('не могу получить токен');
			return;
		} else {
			alert('Токен получен...');
		}

		var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=edit&title=' + encodeURIComponent( mw.config.get('wgPageName') );
		var rq = "summary=" + encodeURIComponent( wgDenyFLP.editsummary ) +
							"&text=" + encodeURIComponent( wgDenyFLP.newtext ) +
							"&token=" + encodeURIComponent( wgDenyFLP.edittoken );

		wgDenyFLP.rq.onreadystatechange = wgDenyFLP.onEditSaved;
		wgDenyFLP.rq.open( "POST", uri, true );
		wgDenyFLP.rq.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
		wgDenyFLP.rq.send( rq );
	},

	'onEditSaved' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;

		result = eval('('+this.responseText+')');
		if( typeof( result.error ) != 'undefined' ) {
			alert( "Не удалось сохранить страницу: " + result.error.info );
			sendError(result.error.info + ' — в <onEditSaved>');
			return;
		} else {
			alert('Страница ' + mw.config.get('wgPageName') + ' обновлена...');
		}

		var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=edit&title=' + encodeURIComponent( 'Обсуждение' + (wgDenyFLP.isPortal ? ' портала' : '') + ':' + mw.config.get('wgPageName') );
		var rq = "summary=" + encodeURIComponent( wgDenyFLP.editsummary ) +
							"&prependtext=" + encodeURIComponent( wgDenyFLP.talktext ) +
							"&token=" + encodeURIComponent( wgDenyFLP.edittoken );

		wgDenyFLP.rq.onreadystatechange = wgDenyFLP.onNominationSaved;
		wgDenyFLP.rq.open( "POST", uri, true );
		wgDenyFLP.rq.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
		wgDenyFLP.rq.send( rq );
	},

	'onNominationSaved' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;

		result = eval('('+this.responseText+')');
		if( typeof( result.error ) != 'undefined' ) {
			alert( "Не удалось сохранить страницу: " + result.error.info );
			sendError(result.error.info + ' — в <onNominationSaved>');
			return;
		} else {
			alert('Страница обсуждения страницы ' + mw.config.get('wgPageName') + ' обновлена...');
		}

		var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=query&prop=revisions&rvprop=content&rvlimit=1&titles=' +
							encodeURIComponent( 'Википедия:Кандидаты_в_избранные_списки_и_порталы' );
		wgDenyFLP.rq.onreadystatechange = wgDenyFLP.onLogDownload;
		wgDenyFLP.rq.open( "GET", uri, true );
		wgDenyFLP.rq.send( "" );
	},

	'onLogDownload' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;

		result = eval('('+this.responseText+')');
		var pgtext = ch(result.query.pages).revisions[0]['*'];
		var nominationRegex = "\\|-(?: {0,})\\n(?:\\|(?: {0,})(?:rowspan=\"?(?:\\d+)\"?(?: {0,})\\|(?: {0,}))?\\[{2}(?:Википедия|ВП):Кандидаты в избранные списки и порталы\\/" + wgDenyFLP.date + "\\|\\d{1,2} [а-я]+\\]{2}(?: {0,})\\n)?\\|(?: {0,})\\[{2}" + replTitle(true) + "\\]{2}(?: {0,})\\n\\|(?: {0,})(?:.*)(?: {0,})\\n\\|(?: {0,})(.*)(?: {0,})";
		
		if (!pgtext.match(nominationRegex)) {
			alert('Редактирование невозможно: не найдена запрашиваемая строка в статье <Википедия:Кандидаты в избранные списки и порталы>');
			sendError('не найдена запрашиваемая строка в статье [[Википедия:Кандидаты в избранные списки и порталы]]');
			return;
		}
		var match = pgtext.match( nominationRegex );
	
		var allText = match[0];
		var endText = match[1];
		
		var text = allText.replace( '|-', '|- class="shadow"');
		text = text.replace( endText, ( wgDenyFLP.isPortal ? "Портал" : "Список" ) + ' отправлен на доработку' );
			
		wgDenyFLP.newtext = pgtext.replace( allText, text);
		wgDenyFLP.editsummary = ( wgDenyFLP.isPortal ? "Портал" : "Список" ) + " [[" + replTitle() + "]] отправлен на доработку [[ВП:ИСП]] " + wgMakeFLP.summarySuffix;
	
		var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=edit&title=' +
							encodeURIComponent( 'Википедия:Кандидаты_в_избранные_списки_и_порталы' );
		var rq = "summary=" + encodeURIComponent( wgDenyFLP.editsummary ) +
							"&text=" + encodeURIComponent( wgDenyFLP.newtext ) +
							"&token=" + encodeURIComponent( wgDenyFLP.edittoken );

		wgDenyFLP.rq.onreadystatechange = wgDenyFLP.onLogSaved;
		wgDenyFLP.rq.open( "POST", uri, true );
		wgDenyFLP.rq.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
		wgDenyFLP.rq.send( rq );
	},

	'onLogSaved' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;

		result = eval('('+this.responseText+')');
		if( typeof( result.error ) != 'undefined' ) {
			alert( "Не удалось сохранить страницу: " + result.error.info );
			sendError(result.error.info + ' — в <onLogSaved>');
			return;
		} 

	var now = new Date();
	nowYear = now.getFullYear();
	nowMonth = now.getMonth();
	
	var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=query&prop=revisions&rvprop=content&rvlimit=1&titles=' +
							encodeURIComponent( 'Википедия:Кандидаты_в_избранные_списки_и_порталы/Архив/' + wgDenyFLP.months[nowMonth] + '_' + nowYear );   
		wgDenyFLP.rq.onreadystatechange = wgDenyFLP.arxivDownload;
		wgDenyFLP.rq.open( "GET", uri, true );
		wgDenyFLP.rq.send( "" );
	},

	'arxivDownload' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;

		result = eval('('+this.responseText+')');
		var pgtext = ch(result.query.pages).revisions[0]['*'];
		
	var date = wgDenyFLP.date.split('-');
	var nominationDate = date[2] + ' ' + wgDenyFLP.months_to[date[1] - 1];
		var today = '{{' + 'subst:CURRENTDAY}} {{' + 'subst:CURRENTMONTHNAMEGEN}} {{' + 'subst:CURRENTYEAR}}';  
		var reText = '|- style="background-color:silver;"\n| [[Википедия:Кандидаты в избранные списки и порталы/' + wgDenyFLP.date + '|' + nominationDate + ']]\n| [[' + replTitle() + ']]\n| ' + (wgDenyFLP.isPortal ? 'Портал': 'Список') + ' отправлен на доработку ' + today + ' года\n|}';
	
	wgDenyFLP.newtext = pgtext.replace( '|}', reText);
		wgDenyFLP.editsummary = (wgDenyFLP.isPortal ? "Портал": "Список") + " [[" + replTitle() + "]] отправлен на доработку [[ВП:ИСП]] " + wgMakeFLP.summarySuffix;
	
		var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=edit&title=' +
							encodeURIComponent( 'Википедия:Кандидаты_в_избранные_списки_и_порталы/Архив/' + wgDenyFLP.months[nowMonth] + '_' + nowYear );
		var rq = "summary=" + encodeURIComponent( wgDenyFLP.editsummary ) +
							"&text=" + encodeURIComponent( wgDenyFLP.newtext ) +
							"&token=" + encodeURIComponent( wgDenyFLP.edittoken );

		wgDenyFLP.rq.onreadystatechange = wgDenyFLP.onArxivDownload;
		wgDenyFLP.rq.open( "POST", uri, true );
		wgDenyFLP.rq.setRequestHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
		wgDenyFLP.rq.send( rq );  
	},

	'onArxivDownload' : function() {
		if( this.readyState != 4 ) return;
		if( this.status != 200 ) return;

		result = eval('('+this.responseText+')');
		if( typeof( result.error ) != 'undefined' ) {
			alert( "Не удалось сохранить страницу: " + result.error.info );
			sendError(result.error.info + ' — в <onArxivDownload>');
			return;
		}

	mw.notify( 'Страница успешно отравлена на доработку. <a href="javascript:location.reload()">Перезагрузить страницу</a>' );
	},

	'deny' : function() {
		var uri = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + '/api.php?format=json&action=query&prop=revisions&rvprop=content&rvlimit=1&titles=' + encodeURIComponent( mw.config.get('wgPageName') );
		this.rq = new XMLHttpRequest();
		this.rq.onreadystatechange = this.onTextDownload;
		this.rq.open( "GET", uri, true );
		this.rq.send( "" );
	}
} 

if ( isOfficer() ) {
	$( wgMakeFLP.addMakeFeaturedTab );
	$( wgDenyFLP.addDenyTab );
}

/* </nowiki> */
Источник —

Same as Gadget-featuredlists.js