ميدياويكي:TofawikiConsole.js

من ويكي‌حج

ملاحظة: بعد النشر، أنت قد تحتاج إلى إفراغ الكاش الخاص بمتصفحك لرؤية التغييرات.

  • فايرفوكس / سافاري: أمسك Shift أثناء ضغط Reload، أو اضغط على إما Ctrl-F5 أو Ctrl-R (⌘-R على ماك)
  • جوجل كروم: اضغط Ctrl-Shift-R (⌘-Shift-R على ماك)
  • إنترنت إكسبلورر/إيدج: أمسك Ctrl أثناء ضغط Refresh، أو اضغط Ctrl-F5
  • أوبرا: اضغط Ctrl-F5.
$(function () {
	'use strict';
	
	document.title = 'به‌ویکی‌فا انبوه - ویکی‌پدیا، دانشنامهٔ آزاد';

	if (mw.config.get('wgCanonicalSpecialPageName') !== 'Blankpage' ||
			mw.config.get('wgPageName').split('/')[1] !== 'tofawiki-conosle') {
		return;
	}
	
	/* if (mw.config.get('wgUserGroups').every(function (x) {
			return ['bot', 'autopatrolled', 'patroller', 'sysop', 'eliminator'].indexOf(x) === -1;
		})) {
		$('#content').empty().append('متأسفانه این ابزار به کاربران دارای دسترسی گشت خودکار محدود شده است.');
		return;
	}*/

	window.onbeforeunload = function () {
		if ($('#tofawiki-main').width() && $('#tofawiki-main').val() === '') {
			return;
		}
		return 'پیش از اتمام صفحه را ترک نکنید';
	};
	
	var methods = {
		city: {
			title: 'شهر و مکان‌های مسکونی',
			summary: 'Rezabot',
			generateContent: function (request) {
				return $.getJSON(new mw.Uri('//rezabot.toolforge.org/a.php').extend({
					fawiki: request[0],
					enwiki: request[1]
				}));
			},
			extraInfo: $('<div>').append(
				'<div>در پنجرهٔ پایین نام فارسی و انگلیسی مقالهٔ ناموجود را بنویسید و دکمهٔ درخواست را بزنید. بعد از چند دقیقه ربات متن مقاله و پیش‌نمایش آنرا در اختیارتان می‌گذارد. بعد از اعمال تغییرات دکمهٔ ایجاد را بزنید. مانند:</div>',
				'<br><div>شیراز@Shiraz</div>',
				'<br><div>تهران@Tehran</div>',
				'<br><div>اصفهان@Isfahan</div>',
				'<br>شهرهای ناموجود مهم در ',
				'<b><a href="//fa.wikipedia.org/wiki/ویکی‌پدیا:گزارش_دیتابیس/شهرهای_ناموجود" target="_blank">اینجا</a></b>',
				' فهرست شده‌اند؛ با کلیک بر روی موضوع مقاله می‌توانید مقالات شهرها را مشاهده کنید.<br>'
			),
			placeholder: 'عنوان @ Title',
			enableCheckButton: true,
			enableFirstAidsButton: true
		},

		general: {
			title: 'اشخاص، آرایه‌های زیستی، فیلم، موسیقی، رود، ساختمان و بازی‌های ویدئویی',
			summary: 'Dexbot',
			generateContent: function (request) {
				return $.getJSON('//tofawiki.wmcloud.org/translate/enwiki/' + request[1] + '/' + request[0]);
			},
			extraInfo: $('<div>').append(
				'<div>در پنجرهٔ پایین نام فارسی و انگلیسی مقالهٔ ناموجود را بنویسید و دکمهٔ درخواست را بزنید. بعد از چند دقیقه ربات متن مقاله و پیش‌نمایش آنرا در اختیارتان می‌گذارد. بعد از اعمال تغییرات دکمهٔ ایجاد را بزنید.</div>',
				'<br>مقاله‌های ناموجود مهم در ',
				'<b><a href="//fa.wikipedia.org/wiki/ویکی‌پدیا:گزارش_دیتابیس/مقاله‌های_مهم_ایجادنشده" target="_blank">اینجا</a></b>',
				' فهرست شده‌اند؛ با کلیک بر روی موضوع مقاله می‌توانید برپایهٔ موضوع آنها را مرتب و انتخاب کنید.<br>'
			),
			placeholder: 'عنوان @ Title',
			enableCheckButton: true,
			enableFirstAidsButton: true
		},
		
		redirect: {
			title: 'تغییرمسیر',
			summary: 'فهرست ورودی',
			generateContent: function (request) {
				return $.Deferred().resolve({
					page_content: '#' + 'تغییرمسیر [' + '[' + request[1] + ']]'
				});
			},
			noLanguageLinks: true,
			extraInfo: '',
			placeholder: 'مبدأ تغییر مسیر @ مقصد (عنوان مقالهٔ اصلی)',
			creationExtraTool: function () {
				var destination = location.hash.split('|')[1];

				if (!destination)
					return;

				destination = decodeURI(destination);
				
				var ns = 0;
				
				var pageNameParts = destination.split(/:/);
				if (pageNameParts.length > 1) {
					var possibleNs = mw.config.get('wgNamespaceIds')[pageNameParts[0]];

					if (possibleNs !== undefined) {
						ns = possibleNs;
						destination = pageNameParts.slice(1).join(':');
					}
				}
				
				var namespaces = {
					0: '',
					2: 'کاربر:',
					4: ['وپ:', 'ویکی\u200cپدیا:'],
					6: 'پرونده:',
					8: 'مدیاویکی:',
					10: 'الگو:',
					12: 'راهنما:',
					14: 'رده:',
					100: 'درگاه:',
					102: 'کتاب:',
					446: 'برنامه آموزشی:',
					828: 'پودمان:'
				};
		
				var append = '@';
				var buttonText = '@';
				if (typeof namespaces[ns] === 'object') {
					append = namespaces[ns][0] + '@' + namespaces[ns][1] + destination;
					buttonText = namespaces[ns][0] + '@صفحهٔ قبل';
				} else if (typeof namespaces[ns] === 'string') {
					append = namespaces[ns] + '@' + namespaces[ns] + destination;
					buttonText = namespaces[ns] + '@' + destination;
				}

				return $('<span>', {
					text: buttonText,
					class: 'mw-ui-button mw-ui-constructive'
				}).click(function () {
					var value = $('#tofawiki-main').val().trim();
					if (value !== '')
						value = value + '\n';
					value = value + append;
					$('#tofawiki-main').val(value).focus();
				});
			},
			editBoxRows: 2,
			previewHeight: 60,
			autoCreate: true
		},

		category: {
			title: 'رده',
			summary: 'فهرست ورودی',
			generateContent: function (request) {
				var enlink = request[1].replace(/\_/g, ' ');
				return $.post('//tofawiki-linkstranslator.wmcloud.org/', { p: enlink }).then(function (result) {
					if (Object.keys(result).length) {
						return $.Deferred().reject('صفحهٔ معادل قبلاً وجود داشت');
					}
					return catParents(enlink);
				}).then(function (parents) {
					if (!parents) {
						return $.Deferred().reject('صفحهٔ "' + enlink + '" در ویکی مبدأ وجود ندارد یا خود دارای رده نیست');
					}
					return $.post('//tofawiki-linkstranslator.wmcloud.org/', {
						p: parents.join('|')
					})
				}).then(function (translatedParents) {
					return getWikidataEntity(enlink).then(function (entity) {
						var text = Object.keys(translatedParents).map(function (x) {
							return translatedParents[x];
						}).sort(function (x, y) {
							var keyX = dePersian(x),
								keyY = dePersian(y);
							if (keyX < keyY) { return -1; }
							if (keyX > keyY) { return 1; }
							return 0;
						}).map(function (x) {
							return '[[' + x + ']]';
						}).join('\n') + '\n\n[' + '[en:' + enlink + ']]';

						if (entity.claims && entity.claims.P373)
							text = '{' + '{انبار-رده}}\n' + text;
						if (entity.claims && entity.claims.P301)
							text = '{' + '{اصلی رده}}\n' + text;

						return { page_content: text };
					});
				});
			},
			afterSaveAction: function (pageTitle) {
				var defer = $.Deferred();
				var status = $('<span>', { text: 'درخواست پر کردن ' + pageTitle + '…' });
				mw.notify(status, { autoHide: false });
				setTimeout(function () {
					return $.get('//rezabot.toolforge.org/fillcat.php', {
						title: pageTitle,
						fawiki: pageTitle.replace(/ /g, '_'),
						user: 'کاربر:' + mw.config.get('wgUserName'),
						namespace: 14
					}).then(function () {
						status.text('درخواست پر کردن ' + pageTitle + ' با موفقیت داده شد.');
						defer.resolve();
					}, defer.resolve);
				}, 2000);
				return defer;
			},
			extraInfo: $('<div>').append(
				'درخواست\u200cهای ساخت رده را در خطوط جداگانه مانند مثال زیر وارد کنید:' +
				'<br>رده۱@Cateogry1<br>رده۲@Cateogry2<br>رده۳@Cateogry3<br><b>نکات مهم:</b><ol>' +
				'<li>رده‌ها باید شیوه‌نامه <a href="//fa.wikipedia.org/w/index.php?title=ویکی‌پدیا:ترجمه_رده‌ها" target="ویکی‌پدیا:ترجمه رده‌ها">ویکی‌پدیا:ترجمه_رده‌ها</a> را رعایت کنند.' +
				'<li>رده‌هایی که تازه ساخته می‌شوند نیازی به افزودن به مقالات و صفحات ندارد و این رده‌ها پس از چند ساعت به صورت رباتیک به صفحه‌های مرتبط، اضافه می‌گردند و میان‌ویکی‌شان به ویکی‌داده افزوده می‌شود.' +
				'<li>ابزار رده‌هایی که در ویکی‌انگلیسی موجود نباشند را نمی‌سازد.<br>' +
				'<li>ابزار رده‌هایی که رده مادر نداشته باشند یا همسنگ رده مادر در ویکی‌پدیای فارسی نباشد یا همهٔ رده‌های مادرشان رده پنهان باشد را نمی‌سازد.(رده رده‌بندی نشده نمی‌سازد)<br>' +
				'<li>اگر رده‌ای را که پیشنهاد دادید ساخته نشده‌است، ممکن است [[ویژه:پالایهٔ_خرابکاری/91]] از عمل شما جلوگیری کرده باشد (دقت کنید که شرایط موجود در <a href="//fa.wikipedia.org/w/index.php?title=مدیاویکی:Abusefilter-warning-category" target="مدیاویکی:Abusefilter-warning-category">مدیاویکی:Abusefilter-warning-category</a> را رعایت کرده‌اید.)' +
				'</ol>'
			),
			placeholder: 'عنوان رده به فارسی @ Title',
			editBoxRows: 7,
			previewHeight: 60
		},

		disambig: {
			title: 'ابهام‌زدایی و مجموعه نمایه',
			summary: 'Rezabot',
			generateContent: function (request) {
				return $.getJSON(new mw.Uri('//rezabot.toolforge.org/disambig.php').extend({
					fawiki: request[0],
					enwiki: request[1]
				}));
			},
			extraInfo: $('<div>').append(
				'<div>در پنجرهٔ پایین نام فارسی و انگلیسی مقالهٔ ناموجود را بنویسید و دکمهٔ درخواست را بزنید. بعد از چند دقیقه ربات متن صفحهٔ ابهام‌زدایی و پیش‌نمایش آنرا در اختیارتان می‌گذارد. بعد از اعمال تغییرات دکمهٔ ایجاد را بزنید. مانند:</div>',
				'<br><div>شیراز@Shiraz</div>',
				'<br><div>تهران@Tehran</div>',
				'<br><div>اصفهان@Isfahan</div>',
				'<br><div>نکته مهم: ممکن است نیاز باشد از الگوهای {{مقالات مجموعه‌نمایه}}، {{نام خانوادگی}}، {{نام کوچک}} و… به جای {{ابهام‌زدایی}} استفاده کنید برای اطلاعات بیشتر <a href="//fa.wikipedia.org/w/index.php?title=ویکی‌پدیا:ابهام‌زدایی" target="ویکی‌پدیا:ابهام‌زدایی">ویکی‌پدیا:ابهام‌زدایی</a> و <a href="//fa.wikipedia.org/w/index.php?title=ویکی‌پدیا:مقالات_مجموعه‌نمایه" target="ویکی‌پدیا:مقالات_مجموعه‌نمایه">ویکی‌پدیا:مقالات مجموعه‌نمایه</a> را مطالعه کنید.</div>',
			),
			placeholder: 'عنوان @ Title',
			enableCheckButton: true,
			enableFirstAidsButton: true
		},

		custom: {
			title: 'شخصی (پیشرفته)',
			summary: 'الگوی شخصی',
			generateContent: function (request) {
				return $.Deferred().resolve({
					page_content: '{{جا:' + $('#tofawiki-customtemplate').val() + '|' + request.map(function (x, i) {
						return (i + 1) + '=' + x;
					}).join('|') + '}}'
				});
			},
			afterSaveUtils: function (pageTitle) {
				return $('<button>', { style: 'font-size: 100%' }).text('درخواست افزودن نگارخانه و ردهٔ همسنگ').click(function () {
					var button = $(this);
					button.text('در حال انجام…').attr('disabled', '');
					
					$.get('//rezabot.toolforge.org/getbox.php', {
						title: pageTitle,
						fawiki: pageTitle.replace(/ /g,'_'),
						user: 'کاربر:' + mw.config.get('wgUserName'),
						namespace: 0
					}).then(function(result) {
						return $.get('//rezabot.toolforge.org/fillcatArticle.php', {
							title: pageTitle,
							fawiki: pageTitle.replace(/ /g,'_'),
							user: 'کاربر:' + mw.config.get('wgUserName'),
							namespace: 0
						});
					}).then(function () {
						button.text('انجام شد');
					});
				});
			},
			extraInfo: $('<div>').append(
				'راهنمای <b><a href="//fa.wikipedia.org/wiki/راهنما:ساخت_مقاله_به_کمک_الگوی_شخصی_با_ابزار_به_ویکی‌فا_انبوه" target="_blank">ساخت مقاله به کمک الگوی شخصی با ابزار به ویکی‌فا انبوه</a></b> اطلاعات بسیار خوبی رابطه جهت استفاده از این قسمت می‌دهد.<br><br>',
				'به طور خلاصه برای استفاده از این ابزار کافی‌ست فایل اکسل را در جعبهٔ زیر کپی کنید و الگوی تراگنجایش را مشخص کنید.',
				'<br>',
				'<b>نکته:</b> متغیر۱ برابر با نام مقاله و متغیر۲ برابر با میان‌ویکی‌ست و سایر متغیرها هم برای معرفی بخش‌های تغییرپذیر مقاله کاربرد دارند.'
			),
			placeholder: 'متغیر۱ (نام مقاله)\tمتغیر۲ (ترجیحاً عنوان انگلیسی)\tمتغیر۳\tمتغیر۴\t…',
			enableCheckButton: true,
			enableFirstAidsButton: true
		}
	};
	
	// ابزارهای رده
	function catParents(title) {
		return new mw.Api({ ajax: { url: '//ar.wikihaj.com/api.php' } }).get({
			action: 'query',
			prop: 'categories',
			titles: title,
			clshow: '!hidden',
			cllimit: 500,
			format: 'json',
			origin: window.location.protocol + '//' + window.location.hostname
		}).then(function (data) {
			return (data.query.pages[Object.keys(data.query.pages)[0]].categories || []).map(function (x) { return x.title; });
		});
	}
	
	function getWikidataEntity(entitle) {
		return new mw.Api({ ajax: { url: '//www.wikidata.org/w/api.php' } }).get({
			action: 'wbgetentities',
			format: 'json',
			sites: 'enwiki',
			titles: entitle,
			normalize: 'true',
			origin: window.location.protocol + '//' + window.location.hostname
		}).then(function (x) { return x.entities[Object.keys(x.entities)[0]]; });
	}

	function pageExists(page) {
		return new mw.Api({ ajax: { url: '//ar.wikihaj.org/api.php' } }).get({
			action: 'query',
			titles: page,
			format: 'json'
		}).then(function (data) { return data.query.pages['-1'] === undefined; });
	}
	
	function dePersian(text) {
		return text
			.replace(/ی/g, 'ي')
			.replace(/ک/g, 'ك')
			.replace(/گ/g, 'كی')
			.replace(/ژ/g, 'زی')
			.replace(/چ/g, 'جی')
			.replace(/پ/g, 'بی');
	}
	////
	
	$('#content').empty().append($('<div>', { id: 'tofawiki-console' }).css({
		border: '2px solid #b3000b',
		padding: '1em',
		'background-color': '#fefce3',
		'margin-bottom': '8px',
		'border-radius': '15px'
	}).append($('<div>', { id: 'tofawiki-console-input' }).append(
		'نوع: ',
		$('<select>', { id: 'tofawiki-select', style: 'font-size: 120%' }).append(Object.keys(methods).map(function (id) {
			return $('<option>', { value: id }).text(methods[id].title);
		})).change(function () {
			if ($(this).val() === 'custom') {
				$('#tofawiki-custom').show();
				$('#tofawiki-delimiter').val('\t');
			} else {
				$('#tofawiki-custom').hide();
				$('#tofawiki-delimiter').val('@');
			}
			
			var method = methods[$(this).val()];
			$('#tofawiki-extrainfo').empty().append(method.extraInfo);
			$('#tofawiki-main').attr('placeholder', method.placeholder);
			$('#tofawiki-creationextratool').empty().append(method.creationExtraTool
				? method.creationExtraTool()
				: '');
			$('#tofawiki-checkbutton').toggle(method.enableCheckButton);
			$('#tofawiki-firstaidsbutton').toggle(method.enableFirstAidsButton);
		}),
		'<br>',
		'جداکننده&nbsp;',
		$('<select>', { id: 'tofawiki-delimiter' }).append(
			$('<option>', { value: '@' }).text('@'),
			$('<option>', { value: '|' }).text('|'),
			$('<option>', { value: '\t' }).text('تب')
		),
		'<br>',
		$('<div>', { id: 'tofawiki-custom' }).append(
			'الگو برای تراگنجایش: ',
			$('<input>', { id: 'tofawiki-customtemplate' })
		).hide(),
		'<br>',
		$('<div>', { id: 'tofawiki-extrainfo' }),
		'<br>',
		$('<div>', { id: 'tofawiki-creationextratool' }).css({ position: 'absolute', left: '2.5em' }),
		$('<textarea>', {
			id: 'tofawiki-main',
			style: 'font-size: 150%',
			rows: 10
		}),
		$('<button>', { style: 'font-size: 100%', text: 'درخواست' }).click(function () {
			var method = methods[$('#tofawiki-select').val()];
			var delimiter = $('#tofawiki-delimiter').val();

			var requests = resolveUserRequests(delimiter);
			$('#tofawiki-console-input').hide();
			$('#tofawiki-console').append(
				$('<div>', { id: 'tofawiki-progress' }),
				'<br><hr><br>'
			);
			var current = 1;
			var success = 0;
			requests.map(function (request) {
				var row = $('<div>', {
					'class': 'tofawiki-row',
					style: 'border-bottom: 1px solid; margin-bottom: 1em; padding-bottom:1em;'
				}).appendTo('#tofawiki-console');
				return function generateText() {
					var fawiki = request[0].replace(/ي/g, 'ی').replace(/ك/g, 'ک');
					var enwiki = request[1];
					
					var promise = method.generateContent(request).then(function (result) {
						return result.error
							? $.Deferred().reject(result.error)
							: preSavedTransform(result.page_content, fawiki);
					});

					$('#tofawiki-progress').text('در حال دریافت «' + fawiki
						+ '» (' + (current++).toLocaleString('fa') + ' از ' +
						requests.length.toLocaleString('fa') + ')');

					return promise.then(function (content) {
						if (window.persianWikiTools) {
							content = persianWikiTools.superTool(content);
						}
						var textarea = $('<textarea>', { cols: 80, rows: method.editBoxRows || 20, text: content });
						var summary = $('<input>', { style: 'width: 500px;' })
							.val('ایجادشده به کمک [[راهنما:ابزار/به ویکی‌فا|به ویکی‌فا]] انبوه و ' + method.summary + '، ابرابزار');
						var previewElement = $('<div>', { 'class': 'tofawiki-preview' });
						var preview = function () {
							return parseContent(textarea.val(), fawiki).then(function (result) {
								previewElement.css({
									'border': '1px solid grey',
									'padding': '1em',
									'height': method.previewHeight || 270,
									'overflow-y': 'scroll'
								}).html(result).append('<div style="clear: both">');
							});
						};
						preview();
						var againInput = $('<input>').val(request.join(delimiter));
						
						row.empty().append(
							$('<div>', { style: 'font-size: 150%;' }).text(fawiki),
							textarea,
							'<br>',
							summary,
							'<br><br>',
							previewElement,
							'<br>',
							$('<button>', { style: 'font-size: 100%', 'class': 'tofawiki-row-create-button', text: 'ایجاد' }).click(function () {
								var content = textarea.val();
								var summaryText = summary.val();
								row.empty().append('در حال ایجاد ' + fawiki + '…');
								createPage(fawiki, content, summaryText).then(function () {
									pageExists(fawiki).then(function (exists) {
										if (!exists) {
											row.empty().append(
												'«', $('<a>', { text: fawiki, target: '_blank', href: mw.util.getUrl(fawiki) }), '» به دلیل خطا ایجاد نشد! (ممکن است خطای پالایه باشد)',
												method.afterSaveUtils ? method.afterSaveUtils(fawiki) : ''
											);
										} else {
											row.empty().append(
												'«', $('<a>', { text: fawiki, target: '_blank', href: mw.util.getUrl(fawiki) }), '» ایجاد شد ',
												method.afterSaveUtils ? method.afterSaveUtils(fawiki) : ''
											);
										}
									})
									if (++success === requests.length) {
										window.onbeforeunload = undefined;
									}
									if (method.noLanguageLinks)
										return;

									return $.when(wikidataToken(), getWikidataId(enwiki)).then(function (token, id) {
										return addWikidataSitelink(token, id, fawiki, 'fawiki');
									}).then(undefined, function () { return $.Deferred().resolve(); }).then(function () {
										return $.get('//dexbot.toolforge.org/interwikidata.php', { page: fawiki });
									}).then(undefined, function () { return $.Deferred().resolve(); }).then(function () {
										if (method.afterSaveAction) return method.afterSaveAction(fawiki);
									});
								}, function (error) {
									var retryInput = $('<input>').val(request.join(delimiter));
									row.empty().append(
										$('<span>', {
											style: 'color: red;',
											text: error === 'articleexists'
												? 'صفحه‌ای به این عنوان در حال حاضر وجود دارد'
												: error
										}),
										'<br>',
										retryInput,
										$('<button>').text('تلاش مجدد').click(function () {
											request = retryInput.val().split(delimiter);
											row.empty().html('تلاش مجدد…');
											generateText();
										})
									);
								});
							}),
							' ',
							$('<button>').css('font-size', '100%').text('به‌روزرسانی پیش‌نمایش').click(function () {
								var button = $(this);
								button.attr('disabled', '');
								preview().then(function () {
									button.prop('disabled', false);
								});
							}),
							' ',
							window.persianWikiTools ? $('<img>', {
								src: '//upload.wikimedia.org/wikipedia/fa/f/fc/Button_super_tool.png'
							}).click(function () {
								textarea.val(persianWikiTools.superTool(textarea.val()));
							}) : '',
							'<br><br>',
							againInput,
							$('<button>').text('تهیه مجدد').click(function () {
								request = againInput.val().split(delimiter);
								row.empty().html('تهیه مجدد…');
								generateText();
							})
						);
					}).then(undefined, function (error) {
						error = error || 'ایجاد ' + fawiki + ' ناموفق بود';
						parseContent(error).then(function (parsedError) {
							var retryInput = $('<input>').val(request.join(delimiter));
							row.empty().append(
								$('<span>', {
									style: 'color: red;',
									html: parsedError
								}),
								retryInput,
								$('<button>').text('تلاش مجدد').click(function () {
									request = retryInput.val().split(delimiter);
									row.empty().html('تلاش مجدد…');
									generateText();
								})
							);
						});
						return $.Deferred().resolve();
					});
				};
			}).reduce(function (defer, job) {
				return defer.then(job);
			}, $.Deferred().resolve()).then(function () {
				$('#tofawiki-progress').empty();
				
				function createAll() {
					var createAllButton = $('#tofawiki-createallbutton');
					createAllButton.prop('disabled', 'disabled');
					$('.tofawiki-row-create-button').get().map(function (button) {
						return function () {
							$(button).click();
							var defer = $.Deferred();
							setTimeout(defer.resolve, 1000);
							return defer;
						};
					}).reduce(function (defer, job) {
						return defer.then(job);
					}, $.Deferred().resolve()).then(function () {
						createAllButton.hide();
					});
				}
				
				if (mw.config.get('wgUserGroups').indexOf('bot') !== -1) {
					$('#tofawiki-progress').append($('<button>', {
						id: 'tofawiki-createallbutton',
						text: 'ایجاد همه'
					}).click(createAll));
				}
				if (method.autoCreate) {
					createAll();
				}
			});
			$('#tofawiki-console').append('<br>اصل درخواست‌ها: ', $('<div>', {
				style: 'margin: 1em; padding: 0.4em; border: 1px dotted; white-space: pre-wrap;',
				html: requests.map(function (x) { return x.join(delimiter); }).join('<br>')
			}));
		}),
		' ',
		$('<button>', { style: 'font-size: 100%', id: 'tofawiki-checkbutton', text: 'بررسی' }).click(function () {
			var delimiter = $('#tofawiki-delimiter').val();
			var requests = resolveUserRequests(delimiter);
			if (requests.some(function (x) { return x.length !== requests[0].length; })) {
				mw.notify('❌ اندازه‌های ورودی‌ها در خطوط مختلف یکسان نیست! احتمالاً اشتباهی در ورودی وجود دارد.', { autoHide: false });
			}
			var button = $(this);
			button.text('در حال انجام…');
			$.post('//tofawiki-linkstranslator.wmcloud.org/', {
				from: 'fa',
				to: 'fa',
				p: requests.map(function (x) { return x[0]; }).join('|')
			}).then(function (faPages) {
				faPages = Object.keys(faPages);
				$.post('//tofawiki-linkstranslator.wmcloud.org/', {
					from: 'en',
					to: 'fa',
					p: requests.map(function (x) { return x[1]; }).join('|')
				}).then(function (enFaEqus) {
					button.text('بررسی');
					//mw.notify('✔️ بررسی انجام شد!', { autoHide: false });
					mw.notify('تعداد متغییرهای ورودی '+requests[0].length.toString()+' است، مطمئن شوید که الگو تراگنجایش هم همین تعداد متغییر دارد.', { autoHide: false });
					enFaEqus = Object.keys(enFaEqus);
					$('#tofawiki-main').val(requests.map(function (x) {
						if (faPages.indexOf(x[0]) !== -1) {
							x[0] = 'خطا: صفحهٔ موجود > ' + x[0];
						}
						if (enFaEqus.indexOf(x[1]) !== -1) {
							x[1] = 'خطا: ترجمهٔ موجود > ' + x[1];
						}
						return x.join(delimiter);
					}).join('\n'));
				});
			});
		}),
		' ',
		window.persianWikiTools ? $('<img>', {
			src: '//upload.wikimedia.org/wikipedia/fa/f/fc/Button_super_tool.png'
		}).click(function () {
			$('#tofawiki-main').val(persianWikiTools.superToolMove($('#tofawiki-main').val()));
		}) : '',
		' ',
		$('<button>', {
			id: 'tofawiki-firstaidsbutton',
			text: 'اصلاح‌های اولیه ربات استخراج',
			style: 'font-size: 40%'
		}).click(function () {
			$('#tofawiki-main').val($('#tofawiki-main').val().split('\n').map(function (x) {
				var r = x.split('\t');
				if (!r[1]) return '';
				var row = r[1].trim().replace(/^en:/, '').replace(/\)$/, '').split('(⎘');
				if (!row[1]) return '';
				row[1] = persianWikiTools.superToolMove(row[1]
					.replace(/ي/g, 'ی').replace(/ك/g, 'ک').replace(/ة/g, 'ه')
					.replace(/^en:/, '').replace(/أ/g, 'ا').replace(/اء/g, 'ا')
					.replace(/إ/g, 'ا')
					.replace(/عبد ال/g, 'عبدال')
					.replace(/([ \(\)])لاعب([ \(\)])/g, '$1بازیکن$2')
					.replace(/([ \(\)])كرة قدم([ \(\)])/g, '$1فوتبال$2')
					.replace(/([ \(\)])موالید([ \(\)])/g, '$1زاده$2'));
				return row.reverse().join('@') + '\n';
			}).join(''));
		})
	)));
	
	function onHashChange() {
		if (location.hash === '#catmaker') {
			$('#tofawiki-select').val('category');
		}
		if (location.hash && location.hash.split('|')[0] === '#redirectmaker') {
			$('#tofawiki-select').val('redirect');
		}
		$('#tofawiki-select').change();
	}
	$(window).on('hashchange', onHashChange);
	onHashChange();

	function resolveUserRequests(delimiter) {
		return $('#tofawiki-main').val().trim().split('\n')
			.filter(function (x) {
				return x.indexOf(delimiter) !== -1;
			}).map(function (x) {
				if ($('#tofawiki-select').val() === 'category') {
					x = x.replace(/رده:/, '').replace(/Category:/i, '');
				}

				x = x.split(delimiter);
				x[0] = x[0].split('>').slice(-1)[0].trim();
				x[1] = x[1].split('>').slice(-1)[0].trim();

				if ($('#tofawiki-select').val() === 'category') {
					x[0] = 'رده:' + x[0];
					x[1] = 'Category:' + x[1];
				}
				return x;
			});
	}
	
	function parseContent(content, title) {
		return new mw.Api().post({
			action: 'parse',
			text: content,
			contentmodel: 'wikitext',
			prop: 'text',
			pst: '',
			title: title || 'API'
		}).then(function (data) { return data.parse.text['*']; });
	}

	function preSavedTransform(content, title) {
		return new mw.Api().post({
			action: 'parse',
			text: content,
			contentmodel: 'wikitext',
			prop: 'text',
			onlypst: '',
			title: title || 'API'
		}).then(function (data) { return data.parse.text['*']; });
	}
	
	function createPage(title, text, summary) {
		return new mw.Api().post({
			action: 'edit',
			title: title,
			text: text,
			summary: summary || '',
			createonly: '',
			bot: '',
			token: mw.user.tokens.get('csrfToken')
		}).then(function (response) {
			return response.error
				? $.Deferred().reject(response.error)
				: response;
		});
	}
	
	var wikidataTokenCache;
	function wikidataToken() {
		if (wikidataTokenCache) {
			return $.Deferred().resolve(wikidataTokenCache);
		}

		return $.ajax({
			url: '//www.wikidata.org/w/api.php',
			data: {
				action: 'query',
				meta: 'tokens',
				format: 'json',
				origin: location.protocol + '//' + location.hostname
			},
			xhrFields: { withCredentials: true }
		}).then(function (data) {
			var token = data.query.tokens.csrftoken;
			if (token === '+\\') {
				// not logged in
				return $.Deferred().reject('login');
			} else {
				wikidataTokenCache = token;
				return token;
			}
		});
	}

	function getWikidataId(enTitle) {
		return new mw.Api({ ajax: { url: '//www.wikidata.org/w/api.php' } }).get({
			action: 'wbgetentities',
			format: 'json',
			sites: 'enwiki',
			titles: enTitle,
			props: 'info',
			origin: location.protocol + '//' + location.hostname
		}).then(function (x) {
			return x.entities[Object.keys(x.entities)[0]].id;
		});
	}
	
	function addWikidataSitelink(token, wikidataId, title, site) {
		return $.ajax({
			url: '//www.wikidata.org/w/api.php',
			type: 'POST',
			data: {
				action: 'wbsetsitelink',
				format: 'json',
				id: wikidataId,
				linksite: site,
				linktitle: title,
				bot: '1',
				token: token,
				origin: location.protocol + '//' + location.hostname
			},
			xhrFields: { withCredentials: true }
		}).then(function (data) {
			return data.error ? $.Deferred().reject(data.error) : data;
		});
	}
});