مدیاویکی:Gadget-twinklearv-2022.js

از ویکی‌پدیا، دانشنامهٔ آزاد

نکته: برای دیدن تغییرات، ممکن است نیاز باشد که حافظهٔ نهانی مرورگر خود را پس از انتشار پاک‌سازی کنید. گوگل کروم، فایرفاکس، مایکروسافت اج و سافاری: کلید Shift را نگه دارید و روی دکمهٔ Reload در نوار ابزار مرورگر کلیک کنید. برای آگاهی از جزئیات و نحوهٔ پاک‌سازی حافظهٔ نهانی سایر مرورگرها، صفحهٔ ویکی‌پدیا:میانگیر مرورگرتان را خالی کنید را ببینید.

// <nowiki>


(function($) {


/*
 ****************************************
 *** twinklearv.js: ARV module
 ****************************************
 * Mode of invocation:     Tab ("ARV")
 * Active on:              Any page with relevant user name (userspace, contribs, etc.)
 */

Twinkle.arv = function twinklearv() {
	var username = mw.config.get('wgRelevantUserName');
	if (!username || username === mw.config.get('wgUserName')) {
		return;
	}

	var isIP = mw.util.isIPAddress(username, true);
	// Ignore ranges wider than the CIDR limit
	if (Morebits.ip.isRange(username) && !Morebits.ip.validCIDR(username)) {
		return;
	}
	var userType = isIP ? (Morebits.ip.isRange(username) ? 'بازهٔ ' : '') + 'آی‌پی' : 'کاربر';

	Twinkle.addPortletLink(function() {
		Twinkle.arv.callback(username, isIP);
	}, 'گبپ', 'tw-arv', 'گزارش ' + userType + ' به مدیران');
};

Twinkle.arv.callback = function (uid, isIP) {
	var Window = new Morebits.simpleWindow(600, 500);
	Window.setTitle('گزارش و بررسی پیشرفته'); // Backronym
	Window.setScriptName('توینکل');
	Window.addFooterLink('راهنمای تام', 'وپ:مممخ');
	Window.addFooterLink('راهنمای تامنام', 'وپ:تامنام/د');
	Window.addFooterLink('راهنمای دبک', 'وپ:ردب');
	Window.addFooterLink('ترجیحات گبپ', 'وپ::توینکل/ترجیحات#گبپ');
	Window.addFooterLink('راهنمای توینکل', 'وپ:توینکل/توضیحات#گبپ');
	Window.addFooterLink('ارائهٔ بازخورد', 'بوپ:توینکل');

	var form = new Morebits.quickForm(Twinkle.arv.callback.evaluate);
	var categories = form.append({
		type: 'select',
		name: 'category',
		label: 'انتخاب نوع گزارش:',
		event: Twinkle.arv.callback.changeCategory
	});
	categories.append({
		type: 'option',
		label: 'خرابکاری (وپ:تام)',
		value: 'تام'
	});
	categories.append({
		type: 'option',
		label: 'نام کاربری (وپ:تامنام)',
		value: 'نام',
		disabled: isIP
	});
	categories.append({
		type: 'option',
		label: 'زاپاس‌باز (وپ:دبک)',
		value: 'زاپاس‌باز'
	});
	categories.append({
		type: 'option',
		label: 'زاپاس (وپ:دبک)',
		value: 'زاپاس'
	});
	categories.append({
		type: 'option',
		label: 'جنگ ویرایشی (وپ:تام۳)',
		value: 'تام۳',
		disabled: Morebits.ip.isRange(uid) // rvuser template doesn't support ranges
	});
	form.append({
		type: 'div',
		label: '',
		style: 'color: red',
		id: 'twinkle-arv-blockwarning'
	});

	form.append({
		type: 'field',
		label: 'محل کار',
		name: 'work_area'
	});
	form.append({ type: 'submit' });
	form.append({
		type: 'hidden',
		name: 'uid',
		value: uid
	});

	var result = form.render();
	Window.setContent(result);
	Window.display();

	// Check if the user is blocked, update notice
	var query = {
		action: 'query',
		list: 'blocks',
		bkprop: 'range|flags',
		format: 'json'
	};
	if (isIP) {
		query.bkip = uid;
	} else {
		query.bkusers = uid;
	}
	new Morebits.wiki.api("در حال بررسی وضعیت قطع دسترسی کاربر", query, function(apiobj) {
		var blocklist = apiobj.getResponse().query.blocks;
		if (blocklist.length) {
			// If an IP is blocked *and* rangeblocked, only use whichever is more recent
			var block = blocklist[0];
			var message = 'این ' + (isIP ? (Morebits.ip.isRange(uid) ? 'بازهٔ ' : 'نشانی ') + 'آی‌پی' : 'حساب کاربری');
			// Start and end differ, range blocked
			message += block.rangestart !== block.rangeend ? ' به‌عنوان بخشی از یک قطع دسترسی بازه' : '';
			message += (block.partial ? ' به‌طور موردی ' : ' از پیش ') + 'بسته شده‌است';
			if (block.partial) {
				$('#twinkle-arv-blockwarning').css('color', 'black'); // Less severe
			}
			$('#twinkle-arv-blockwarning').text(message);
		}
	}).post();


	// We must init the
	var evt = document.createEvent('Event');
	evt.initEvent('change', true, true);
	result.category.dispatchEvent(evt);
};

Twinkle.arv.callback.changeCategory = function (e) {
	var value = e.target.value;
	var root = e.target.form;
	var old_area = Morebits.quickForm.getElements(root, 'work_area')[0];
	var work_area = null;

	switch (value) {
		case 'تام':
		/* falls through */
		default:
			work_area = new Morebits.quickForm.element({
				type: 'field',
				label: 'گزارش خرابکاری کاربر',
				name: 'work_area'
			});
			work_area.append({
				type: 'input',
				name: 'page',
				label: 'صفحهٔ پیوندشدهٔ اولیه:',
				tooltip: 'برای جلوگیری از پیوند دادن صفحه در گزارش، اینجا را خالی بگذارید',
				value: mw.util.getParamValue('vanarticle') || '',
				event: function(e) {
					var value = e.target.value;
					var root = e.target.form;
					if (value === '') {
						root.badid.disabled = root.goodid.disabled = true;
					} else {
						root.badid.disabled = false;
						root.goodid.disabled = root.badid.value === '';
					}
				}
			});
			work_area.append({
				type: 'input',
				name: 'badid',
				label: 'شناسهٔ نسخهٔ صفحهٔ هدف در زمان  خرابکاری:',
				tooltip: 'برای جلوگیری از درج پیوند تفاوت، اینجا را خالی بگذارید',
				value: mw.util.getParamValue('vanarticlerevid') || '',
				disabled: !mw.util.getParamValue('vanarticle'),
				event: function(e) {
					var value = e.target.value;
					var root = e.target.form;
					root.goodid.disabled = value === '';
				}
			});
			work_area.append({
				type: 'input',
				name: 'goodid',
				label: 'آخرین نسخهٔ سالم صفحهٔ هدف پیش از خرابکاری:',
				tooltip: 'برای جلوگیری از درج پیوند تفاوت به نسخهٔ پیشین، اینجا را خالی بگذارید',
				value: mw.util.getParamValue('vanarticlegoodrevid') || '',
				disabled: !mw.util.getParamValue('vanarticle') || mw.util.getParamValue('vanarticlerevid')
			});
			work_area.append({
				type: 'checkbox',
				name: 'arvtype',
				list: [
					{
						label: 'خرابکاری پس از ارسال آخرین هشدار (سطح ۴)',
						value: 'final'
					},
					{
						label: 'خرابکاری پس از پایان قطع دسترسی اخیر (در بازهٔ یک روزه)',
						value: 'postblock'
					},
					{
						label: 'حساب مشخصاً تنها برای خرابکاری ایجاد شده‌است',
						value: 'vandalonly',
						disabled: mw.util.isIPAddress(root.uid.value, true)
					},
					{
						label: 'حساب ایجادشده برای تبلیغات',
						value: 'promoonly',
						disabled: mw.util.isIPAddress(root.uid.value, true)
					},
					{
						label: 'حساب آشکارا ربات هرزنامه است یا در معرض خطر قرار گرفته است',
						value: 'spambot'
					}
				]
			});
			work_area.append({
				type: 'textarea',
				name: 'reason',
				label: 'توضیح:'
			});
			work_area = work_area.render();
			old_area.parentNode.replaceChild(work_area, old_area);
			break;
		case 'نام':
			work_area = new Morebits.quickForm.element({
				type: 'field',
				label: 'گزارش نام کاربری نامناسب',
				name: 'work_area'
			});
			work_area.append({
				type: 'header',
				label: 'نوع(های) نام کاربری نامناسب',
				tooltip: 'در ویکی‌پدیا استفاده از نام‌های کاربری گمراه‌کننده، تبلیغاتی، توهین‌آمیز یا غیرسازنده مجاز نیست. استفاده از نام دامنه‌های اینترنتی و نشانی‌های ایمیل نیز به‌طور مشابه ممنوع است. این معیار هم به نام‌های کاربری، و هم به امضاها اعمال می‌شود. نام‌های کاربری که در زبان دیگری به‌جز فارسی نامناسب هستند، یا به‌واسطهٔ اشتباه املایی و تغییرات جزئی همچنان نمایندهٔ نامی نامناسب هستند، یا به‌طور غیرمستقیم یا ضمنی ناقض این معیار هستند، همچنان نامناسب محسوب می‌شوند.'
			});
			work_area.append({
				type: 'checkbox',
				name: 'arvtype',
				list: [
					{
						label: 'نام کاربری گمراه‌کننده',
						value: 'گمراه‌کننده',
						tooltip: 'نام‌های کاربری گمراه‌کننده حاوی اطلاعات مرتبط و گمراع‌کننده در مورد مشارکت‌کننده هستند. برای مثال، نکات واقعی گمراه‌کننده، ادعای اختیارات غیرواقعی، یا نام‌های کاربری که تصور ربات بودن کاربر را به ذهن القا می‌کنند.'
					},
					{
						label: 'نام کاربری تبلیغاتی',
						value: 'تبلیغاتی',
						tooltip: 'نام‌های کاربری تبلیغاتی حاوی تبلیغ برای یک شرکت، وبگاه یا گروه هستند. لطاً تا زمانی که کاربر ویرایش‌های تبلیغاتی مرتبط با نام کاربری خود انجام نداده است، این نام‌های کاربری را در تامنام گزارش نکنید.'
					},
					{
						label: 'نام کاربری نشانگر استفادهٔ مشترک',
						value: 'مشترک',
						tooltip: 'نام‌های کاربری که شبههٔ استفادهٔ مشترک را ایجاد می‌کنند (نام شرکت‌ها یا گروه‌ها، یا نام سمت‌های سازمانی) مجاز نیستند. نام‌های کاربری که حاوی نام یک شرکت یا گروه باشند، اما به‌وضوح یک فرد را به‌تنهایی نمایندگی می‌کنند، نظیر «کوروش-ایران‌سازه»، «Mohammadi at XY Foundation», «طرفدار سامسونگ» و غیره.'
					},
					{
						label: 'نام کاربری توهین‌آمیز',
						value: 'توهین‌آمیز',
						tooltip: 'نام‌های کاربری توهین‌آمیز، باعث دشواری ویرایش هماهنگ می‌شوند.'
					},
					{
						label: 'نام‌های کاربری غیرسازنده',
						value: 'مخرب',
						tooltip: 'نام‌های کاربری غیرسازنده شمال ترولینگ آشکار یا حمله‌های شخصی می‌شوند یا این که در عوض قصد کاربر برای ایجاد اخلال در ویکی‌پدیا را به‌طور واضح نشان می‌دهند.'
					}
				]
			});
			work_area.append({
				type: 'textarea',
				name: 'reason',
				label: 'توضیح:'
			});
			work_area = work_area.render();
			old_area.parentNode.replaceChild(work_area, old_area);
			break;

		case 'زاپاس':
			work_area = new Morebits.quickForm.element({
				type: 'field',
				label: 'گزارش حساب زاپاس مشکوک',
				name: 'work_area'
			});
			work_area.append(
				{
					type: 'input',
					name: 'sockmaster',
					label: 'زاپاس‌باز',
					tooltip: 'نام کاربری زاپاس‌باز (حساب اصلی) بدون پیشوند «کاربر:»'
				}
			);
			work_area.append({
				type: 'textarea',
				label: 'دلیل زاپاس بودن:',
				name: 'reasons',
				tooltip: 'شواهدی ارائه کنید که حساب‌ها به هم شباهت دارند. کلی گویی نکنید، پیوند تفاوت بدهید.'
			});
			work_area.append({
				type: 'textarea',
				label: 'شواهد:',
				name: 'evidence',
				tooltip: 'شواهد شما باید به‌طور واضح نشان دهند که هریک از این کاربران احتمالاً در حال سوءاستفاده از چندین حساب کاربری است. معمولاً این به معنی ارائهٔ پیوندهای تفاوت، تاریخچهٔ صفحه‌ها یا اطلاعات دیگری است که توجه می‌کند که چرا کاربران الف) یکسان هستند و ب) مخرب هستند. این اطلاعات تنها باید همان‌هایی باشند که برای قضاوت موضوع مورد نیاز هستند. از سایر مباحثی که شواهدی بر زاپاس‌بازی نیستند بپرهیزید.'
			});
			work_area.append({
				type: 'checkbox',
				list: [
					{
						label: 'درخواست بازرسی کاربر',
						name: 'checkuser',
						tooltip: 'ابزار بازرسی ابزاری است که برای واکشی شواهد فنی مرتبط با یک ادعای زاپاس‌بازی کاربرد دارد. از این ابزار نمی‌توان بدون دلیلی موجه استفاده کرد و وظیفهٔ ارائهٔ این دلیل بر عهدهٔ شماست. مطمئن شوید که شواهد شما دلیلی برای استفاده از این ابزار فراهم کند. این ابزار برای عمومی کردن ارتباط حساب‌های کاربری با نشانی‌های آی‌پی استفاده نخواهد شد.'
					}
				]
			});
			work_area = work_area.render();
			old_area.parentNode.replaceChild(work_area, old_area);
			break;
		case 'زاپاس‌باز':
			work_area = new Morebits.quickForm.element({
				type: 'field',
				label: 'گزارش زاپاس‌باز مشکوک',
				name: 'work_area'
			});
			work_area.append(
				{
					type: 'dyninput',
					name: 'sockpuppet',
					label: 'زاپاس‌ها',
					sublabel: 'زاپاس:',
					tooltip: 'نام کاربری حساب زاپاس بدون پیشوند «کاربر:»',
					min: 2
				});
			work_area.append({
				type: 'textarea',
				label: 'دلیل زاپاس بودن:',
				name: 'reasons',
				tooltip: 'شواهدی ارائه کنید که حساب‌ها به هم شباهت دارند. کلی گویی نکنید، پیوند تفاوت بدهید.'
			});
			work_area.append({
				type: 'textarea',
				label: 'شواهد:',
				name: 'evidence',
				tooltip: 'شواهد شما باید به‌طور واضح نشان دهد که هریک از این کاربران احتمالاً در حال سوءاستفاده از چندین حساب کاربری است. معمولاً این به معنی پیوندهیا تفاوت، تاریخچهٔ صفحه‌ها یا سایر اطلاعاتی است که توجیه می‌کند که چرا این کاربران الف) یکسان هستند و ب) مخرب هستند. این اطلاعات تنها باید همان‌هایی باشند که برای قضاوت موضوع مورد نیاز هستند. از سایر مباحثی که شواهدی بر زاپاس‌بازی نیستند بپرهیزید.'
			});
			work_area.append({
				type: 'checkbox',
				list: [ {
					label: 'درخواست بازرسی',
					name: 'checkuser',
					tooltip: 'ابزار بازرسی ابزاری است که برای واکشی شواهد فنی مرتبط با یک ادعای زاپاس‌بازی کاربرد دارد. از این ابزار نمی‌توان بدون دلیلی موجه استفاده کرد و وظیفهٔ ارائهٔ این دلیل بر عهدهٔ شماست. مطمئن شوید که شواهد شما دلیلی برای استفاده از این ابزار فراهم کند. این ابزار برای عمومی کردن ارتباط حساب‌های کاربری با نشانی‌های آی‌پی استفاده نخواهد شد.'
				} ]
			});
			work_area = work_area.render();
			old_area.parentNode.replaceChild(work_area, old_area);
			break;
		case 'تام۳':
			work_area = new Morebits.quickForm.element({
				type: 'field',
				label: 'گزارش جنگ ویرایشی',
				name: 'work_area'
			});
			work_area.append({
				type: 'input',
				name: 'page',
				label: 'صفحه',
				tooltip: 'صفحه‌ای که در حال گزارش آن هستید'
			});
			work_area.append({
				type: 'button',
				name: 'load',
				label: 'بارگیری',
				event: function(e) {
					var root = e.target.form;

					var date = new Morebits.date().subtract(48, 'hours'); // all since 48 hours

					// Run for each AN3 field
					var getAN3Entries = function(field, rvuser, titles) {
						var $field = $(root).find('[name=' + field + ']');
						$field.find('.entry').remove();

						new mw.Api().get({
							action: 'query',
							prop: 'revisions',
							format: 'json',
							rvprop: 'sha1|ids|timestamp|parsedcomment|comment',
							rvlimit: 500, // intentionally limited
							rvend: date.toISOString(),
							rvuser: rvuser,
							indexpageids: true,
							titles: titles
						}).done(function(data) {
							var pageid = data.query.pageids[0];
							var page = data.query.pages[pageid];
							if (!page.revisions) {
								$('<span class="entry">چیزی یافت نشد</span>').appendTo($field);
							} else {
								for (var i = 0; i < page.revisions.length; ++i) {
									var rev = page.revisions[i];
									var $entry = $('<div/>', {
										class: 'entry'
									});
									var $input = $('<input/>', {
										type: 'checkbox',
										name: 's_' + field,
										value: rev.revid
									});
									$input.data('revinfo', rev);
									$input.appendTo($entry);
									var comment = '<span>';
									// revdel/os
									if (typeof rev.commenthidden === 'string') {
										comment += '(خلاصهٔ پنهان‌شده)';
									} else {
										comment += '«' + rev.parsedcomment + '»';
									}
									comment += ' در <a href="' + mw.config.get('wgScript') + '?diff=' + rev.revid + '">' + new Morebits.date(rev.timestamp).calendar() + '</a></span>';
									$entry.append(comment).appendTo($field);
								}
							}

							// add free form input for resolves
							if (field === 'resolves') {
								var $free_entry = $('<div/>', {
									class: 'entry'
								});
								var $free_input = $('<input/>', {
									type: 'text',
									name: 's_resolves_free'
								});

								var $free_label = $('<label/>', {
									for: 's_resolves_free',
									html: 'نشانی وب تفاوت به‌همراه بحث‌های بیشتر: '
								});
								$free_entry.append($free_label).append($free_input).appendTo($field);
							}
						}).fail(function() {
							$('<span class="entry">خرابی ای‌پی‌آی؛ صفحه را تازه‌سازی کنید و دوباره تلاش کنید</span>').appendTo($field);
						});
					};

					// warnings
					var uid = root.uid.value;
					getAN3Entries('warnings', mw.config.get('wgUserName'), 'بحث کاربر:' + uid);

					// diffs and resolves require a valid page
					var page = root.page.value;
					if (page) {
						// diffs
						getAN3Entries('diffs', uid, page);

						// resolutions
						var t = new mw.Title(page);
						var talk_page = t.getTalkPage().getPrefixedText();
						getAN3Entries('resolves', mw.config.get('wgUserName'), talk_page);
					} else {
						$(root).find('[name=diffs]').find('.entry').remove();
						$(root).find('[name=resolves]').find('.entry').remove();
					}
				}
			});
			work_area.append({
				type: 'field',
				name: 'diffs',
				label: 'خنثی‌سازی‌های کاربر (در ۴۸ ساعت گذشته)',
				tooltip: 'ویرایش‌هایی که باور دارید حاصل خنثی‌سازی هستند را انتخاب کنید'
			});
			work_area.append({
				type: 'field',
				name: 'warnings',
				label: 'هشدارهای ارسال‌شده به کاربر',
				tooltip: 'پیش از گزارش باید به کاربر هشدار کافی داده باشید'
			});
			work_area.append({
				type: 'field',
				name: 'resolves',
				label: 'اقدام‌های برای حل اختلاف',
				tooltip: 'باید پیش از هر چیز برای حل اختلاف نظر در صفحه‌های بحث اقدام کرده باشید'
			});

			work_area.append({
				type: 'textarea',
				label: 'توضیح:',
				name: 'comment'
			});

			work_area = work_area.render();
			old_area.parentNode.replaceChild(work_area, old_area);
			break;
	}
};

Twinkle.arv.callback.evaluate = function(e) {
	var form = e.target;
	var reason = '';
	var comment = '';
	if (form.reason) {
		comment = form.reason.value;
	}
	var uid = form.uid.value;

	var types;
	switch (form.category.value) {

		// Report user for vandalism
		case 'تام':
			/* falls through */
		default:
			types = form.getChecked('arvtype');
			if (!types.length && comment === '') {
				alert('باید دلیلی ارائه دهید');
				return;
			}

			types = types.map(function(v) {
				switch (v) {
					case 'final':
						return 'خرابکاری پس از آخرین هشدار';
					case 'postblock':
						return 'خرابکاری پس از پایان قطع دسترسی اخیر';
					case 'vandalonly':
						return 'رفتار کاربر به‌وضوح نشانگر ایجاد حساب تنها برای خرابکاری';
					case 'promoonly':
						return 'حساب تنها برای اهداف تبلیغاتی استفاده می‌شود';
					case 'spambot':
						return 'حساب کاربری به‌وضوح یک ربات هرزنگاری است یا در معرض خطر است';
					default:
						return 'دلیل ناشناخته';
				}
			}).join('؛ ');


			if (form.page.value !== '') {
				// Allow links to redirects, files, and categories
				reason = 'در {{تغییرمسیر ممنوع|:' + form.page.value + '}}';

				if (form.badid.value !== '') {
					reason += ' ({{تفاوت|' + form.page.value + '|' + form.badid.value + '|' + form.goodid.value + '|تفاوت}})';
				}
				reason += ':';
			}

			if (types) {
				reason += ' ' + types;
			}
			if (comment !== '') {
				reason += (reason === '' ? '' : '. ') + comment;
			}
			reason = reason.trim();
			if (!/[.?؟!;؛]$/.test(reason)) {
				reason += '.';
			}
			reason += ' ~~~~';
			reason = reason.replace(/\r?\n/g, '\n*:');  // indent newlines

			Morebits.simpleWindow.setButtonsEnabled(false);
			Morebits.status.init(form);

			Morebits.wiki.actionCompleted.redirect = 'ویکی‌پدیا:تابلوی اعلانات مدیران';
			Morebits.wiki.actionCompleted.notice = 'گزارش کردن کامل شد';

			var aivPage = new Morebits.wiki.page('ویکی‌پدیا:تابلوی اعلانات مدیران', 'در حال پردازش درخواست تام');
//			aivPage.setPageSection(1); Localized [Removed due to different structure on وپ:تام]
			aivPage.setFollowRedirect(true);

			aivPage.load(function() {
				var text = aivPage.getPageText();
				var $aivLink = '<a target="_blank" href="/wiki/وپ:تام">وپ:تام</a>';

				// check if user has already been reported
				if (new RegExp('\\{\\{\\s*(?:(?:[آ][ی]‌[پ][ی])?خرابکاری|[Uu]serlinks)\\s*\\|\\s*(?:1=)?\\s*' + Morebits.string.escapeRegExp(uid) + '\\s*\\}\\}').test(text)) {
					aivPage.getStatusElement().error('گزارشی از پیش موجود است؛ گزارش جدید افزوده نخواهد شد');
					Morebits.status.printUserText(reason, 'توضیح ارائه‌شده توسط شما در زیر نمایش یافته است؛ در صورت تمایل می‌توان آن را به‌صورت دستی ذیل گزارش موجود دربارهٔ این کاربر در ' + $aivLink + ' اضافه کنید:');
					return;
				}

				// then check for any bot reports
				
				/* no bot report noticeboard on fawiki
				
				var tb2Page = new Morebits.wiki.page('Wikipedia:Administrator intervention against vandalism/TB2', 'Checking bot reports');
				tb2Page.load(function() {
					var tb2Text = tb2Page.getPageText();
					var tb2statelem = tb2Page.getStatusElement();

					if (new RegExp('\\{\\{\\s*(?:(?:[Ii][Pp])?[Vv]andal|[Uu]serlinks)\\s*\\|\\s*(?:1=)?\\s*' + Morebits.string.escapeRegExp(uid) + '\\s*\\}\\}').test(tb2Text)) {
						if (confirm('The user ' + uid + ' has already been reported by a bot. Do you wish to make the report anyway?')) {
							tb2statelem.info('Proceeded despite bot report');
						} else {
							tb2statelem.error('Report from a bot is already present, stopping');
							Morebits.status.printUserText(reason, 'The comments you typed are provided below, in case you wish to manually post them at ' + $aivLink + ':');
							return;
						}
					} else {
						tb2statelem.info('No conflicting bot reports');
					}
				
				no bot report noticeboard on fawiki */

					aivPage.getStatusElement().status('در حال افزودن گزارش جدید...');
					aivPage.setEditSummary('گزارش کردن [[ویژه:مشارکت‌ها/' + uid + '|' + uid + ']].');
					aivPage.setChangeTags(Twinkle.changeTags);
					aivPage.setAppendText('\n\n== خرابکاری ' + uid + ' ==\n*{{' + (mw.util.isIPAddress(uid, true) ? 'آی‌پی خرابکار' : 'کاربر خرابکار') + '|' + (/=/.test(uid) ? '1=' : '') + uid + '}}\n\n: ' + reason); // Indent reason
					aivPage.append();
//				}); 
				
			});
			break;

		// Report inappropriate username
		case 'نام':
			types = form.getChecked('arvtype').map(Morebits.string.toLowerCaseFirstChar);

			var hasShared = types.indexOf('مشترک') > -1;
			if (hasShared) {
				types.splice(types.indexOf('مشترک'), 1);
			}

			if (types.length <= 2) {
				types = types.join(' و ');
			} else {
				types = [ types.slice(0, -1).join('، '), types.slice(-1) ].join(' و ');
			}
			/* var article = 'یک';
			 if (/[aeiouwyh]/.test(types[0] || '')) { // non 100% correct, but whatever, including 'h' for Cockney
				article = 'an';
			} */
			reason = '== [[کاربر:' + uid +  ']] ==\n*{{کاربر-تامنام|1=' + uid + '}}\n\n ';
			if (types.length || hasShared) {
				reason += 'نقض سیاست نام کاربری به‌عنوان یک نام کاربری ' + types +
					(hasShared ? ' که دال بر استفادهٔ مشترک است. ' : '. ');
			}
			if (comment !== '') {
				reason += Morebits.string.toUpperCaseFirstChar(comment) + '. ';
			}
			reason += '~~~~';
			reason = reason.replace(/\r?\n/g, '\n*:');  // indent newlines

			Morebits.simpleWindow.setButtonsEnabled(false);
			Morebits.status.init(form);

			Morebits.wiki.actionCompleted.redirect = 'ویکی‌پدیا:تابلوی اعلانات مدیران/نام‌های کاربری نامناسب';
			Morebits.wiki.actionCompleted.notice = 'گزارش کردن کامل شد';

			var uaaPage = new Morebits.wiki.page('ویکی‌پدیا:تابلوی اعلانات مدیران/نام‌های کاربری نامناسب', 'در حال پردازش درخواست تامنام');
			uaaPage.setFollowRedirect(true);

			uaaPage.load(function() {
				var text = uaaPage.getPageText();

				// check if user has already been reported
				if (new RegExp('\\{\\{\\s*(user-uaa|کاربر-تامنام)\\s*\\|\\s*(1\\s*=\\s*)?' + Morebits.string.escapeRegExp(uid) + '\\s*(\\||\\})').test(text)) {
					uaaPage.getStatusElement().error('کاربر از پیش گزارش شده است.');
					var $uaaLink = '<a target="_blank" href="/wiki/وپ:تامنام">وپ:تامنام</a>';
					Morebits.status.printUserText(reason, 'توضیح ارائه‌شده توسط شما در زیر نمایش یافته است؛ در صورت تمایل می‌توانید آن را به‌صورت دستی ذیل گزارش موجود دربارهٔ این کاربر در ' + $uaaLink + ' اضافه کنید:');
					return;
				}
				uaaPage.getStatusElement().status('در حال افزودن گزارش تازه...');
				uaaPage.setEditSummary('گزارش کردن [[ویژه:مشارکت‌ها/' + uid + '|' + uid + ']].');
				uaaPage.setChangeTags(Twinkle.changeTags);

				// Blank newline per [[Special:Permalink/996949310#Spacing]]; see also [[WP:LISTGAP]] and [[WP:INDENTGAP]]
				uaaPage.setPageText(text + '\n' + reason + '\n');
				uaaPage.save();
			});
			break;

		// WP:SPI
		case 'زاپاس‌باز':
			/* falls through */
		case 'زاپاس':
			var sockParameters = {
				evidence: form.evidence.value.trim(),
				reasons: form.reasons.value.trim(),
				checkuser: form.checkuser.checked
			};

			var puppetReport = form.category.value === 'زاپاس';
			if (puppetReport && !form.sockmaster.value.trim()) {
				alert('نام حساب اصلی برای این حساب زاپاس را وارد نکرده‌اید. می‌توانید این حساب را به‌عنوان یک زاپاس‌باز اصلی گزارش کنید.');
				return;
			} else if (!puppetReport && !form.sockpuppet[0].value.trim()) {
				alert('نام حساب(های) زاپاس برای این زاپاس‌باز را وارد نکرده‌اید. می‌توانید این حساب را به‌عنوان یک حساب زاپاس گزارش کنید.');
				return;
			}

			sockParameters.uid = puppetReport ? form.sockmaster.value.trim() : uid;
			sockParameters.sockpuppets = puppetReport ? [uid] : Morebits.array.uniq($.map($('input:text[name=sockpuppet]', form), function(o) {
				return $(o).val() || null;
			}));

			Morebits.simpleWindow.setButtonsEnabled(false);
			Morebits.status.init(form);
			Twinkle.arv.processSock(sockParameters);
			break;

		case 'تام۳':
			var diffs = $.map($('input:checkbox[name=s_diffs]:checked', form), function(o) {
				return $(o).data('revinfo');
			});

			if (diffs.length < 3 && !confirm('شما کمتر از سه ویرایش حاوی تخلف را انتخاب کرده‌اید. آیا می‌خواهید در هر حال به گزارش کردن ادامه دهید؟')) {
				return;
			}

			var warnings = $.map($('input:checkbox[name=s_warnings]:checked', form), function(o) {
				return $(o).data('revinfo');
			});

			if (!warnings.length && !confirm('شما هیچ ویرایشی که در آن به کاربر هشدار داده‌باشید را انتخاب نکرده‌اید. آیا می‌خواهید در هر حال به گزارش کردن ادامه دهید؟')) {
				return;
			}

			var resolves = $.map($('input:checkbox[name=s_resolves]:checked', form), function(o) {
				return $(o).data('revinfo');
			});
			var free_resolves = $('input[name=s_resolves_free]').val();

			var an3_next = function(free_resolves) {
				if (!resolves.length && !free_resolves && !confirm('شما هیچ ویرایشی که در آن برای حل اختلاف نظر تلاش کرده‌باشید را ارائه نکرده‌اید. آیا می‌خواهید در هر حال به گزارش کردن ادامه دهید؟')) {
					return;
				}

				var an3Parameters = {
					uid: uid,
					page: form.page.value.trim(),
					comment: form.comment.value.trim(),
					diffs: diffs,
					warnings: warnings,
					resolves: resolves,
					free_resolves: free_resolves
				};

				Morebits.simpleWindow.setButtonsEnabled(false);
				Morebits.status.init(form);
				Twinkle.arv.processAN3(an3Parameters);
			};

			if (free_resolves) {
				var query;
				var diff, oldid;
				var specialDiff = /ویژه:تفاوت\/(\d+)(?:\/(\S+))?/i.exec(free_resolves);
				if (specialDiff) {
					if (specialDiff[2]) {
						oldid = specialDiff[1];
						diff = specialDiff[2];
					} else {
						diff = specialDiff[1];
					}
				} else {
					diff = mw.util.getParamValue('diff', free_resolves);
					oldid = mw.util.getParamValue('oldid', free_resolves);
				}
				var title = mw.util.getParamValue('title', free_resolves);
				var diffNum = /^\d+$/.test(diff); // used repeatedly

				// rvdiffto in prop=revisions is deprecated, but action=compare doesn't return
				// timestamps ([[phab:T247686]]) so we can't rely on it unless necessary.
				// Likewise, we can't rely on a meaningful comment for diff=cur.
				// Additionally, links like Special:Diff/123/next, Special:Diff/123/456, or ?diff=next&oldid=123
				// would each require making use of rvdir=newer in the revisions API.
				// That requires a title parameter, so we have to use compare instead of revisions.
				if (oldid && (diff === 'cur' || (!title && (diff === 'next' || diffNum)))) {
					query = {
						action: 'compare',
						fromrev: oldid,
						prop: 'ids|title',
						format: 'json'
					};
					if (diffNum) {
						query.torev = diff;
					} else {
						query.torelative = diff;
					}
				} else {
					query = {
						action: 'query',
						prop: 'revisions',
						rvprop: 'ids|timestamp|comment',
						format: 'json',
						indexpageids: true
					};

					if (diff && oldid) {
						if (diff === 'prev') {
							query.revids = oldid;
						} else {
							query.titles = title;
							query.rvdir = 'newer';
							query.rvstartid = oldid;

							if (diff === 'next' && title) {
								query.rvlimit = 2;
							} else if (diffNum) {
								// Diffs may or may not be consecutive, no limit
								query.rvendid = diff;
							}
						}
					} else {
						// diff=next|prev|cur with no oldid
						// Implies title= exists otherwise it's not a valid diff link (well, it is, but to the Main Page)
						if (diff && /^\D+$/.test(diff)) {
							query.titles = title;
						} else {
							query.revids = diff || oldid;
						}
					}
				}

				new mw.Api().get(query).done(function(data) {
					var page;
					if (data.compare && data.compare.fromtitle === data.compare.totitle) {
						page = data;
					} else if (data.query) {
						var pageid = data.query.pageids[0];
						page = data.query.pages[pageid];
					} else {
						return;
					}
					an3_next(page);
				}).fail(function(data) {
					console.log('API failed :(', data); // eslint-disable-line no-console
				});
			} else {
				an3_next();
			}
			break;
	}
};

Twinkle.arv.processSock = function(params) {
	Morebits.wiki.addCheckpoint(); // prevent notification events from causing an erronous "action completed"

	// prepare the SPI report
	var text = '\n{{جا:درخواست بازرسی|' +
		params.sockpuppets.map(function(sock, index) {
			return 'زاپاس' + mw.language.convertNumber((index + 1)) + '=' + sock;
		}).join('|') + '\n|دلیل نقض سیاست=' + params.evidence + ' \n' +
		'|دلیل زاپاس بودن=' + params.reasons;

	if (params.checkuser) {
		text += '|بازرسی=بله';
	}
	text += '}}';

	var reportpage = 'ویکی‌پدیا:درخواست بازرسی کاربر/' + params.uid;

	Morebits.wiki.actionCompleted.redirect = reportpage;
	Morebits.wiki.actionCompleted.notice = 'گزارش کردن کامل شد';

	var spiPage = new Morebits.wiki.page(reportpage, 'در حال واکشی صفحهٔ بحث');
	spiPage.setFollowRedirect(true);
	spiPage.setEditSummary('افزودن گزارش جدید برای [[ویژه:مشارکت‌ها/' + params.uid + '|' + params.uid + ']].');
	spiPage.setChangeTags(Twinkle.changeTags);
	spiPage.setAppendText(text);
	spiPage.setWatchlist(Twinkle.getPref('spiWatchReport'));
	spiPage.append();

	Morebits.wiki.removeCheckpoint();  // all page updates have been started
};

Twinkle.arv.processAN3 = function(params) {
	// prepare the AN3 report
	var minid;
	for (var i = 0; i < params.diffs.length; ++i) {
		if (params.diffs[i].parentid && (!minid || params.diffs[i].parentid < minid)) {
			minid = params.diffs[i].parentid;
		}
	}

	new mw.Api().get({
		action: 'query',
		prop: 'revisions',
		format: 'json',
		rvprop: 'sha1|ids|timestamp|comment',
		rvlimit: 100, // intentionally limited
		rvstartid: minid,
		rvexcludeuser: params.uid,
		indexpageids: true,
		titles: params.page
	}).done(function(data) {
		Morebits.wiki.addCheckpoint(); // prevent notification events from causing an erronous "action completed"

		// In case an edit summary was revdel'd
		var hasHiddenComment = function(rev) {
			if (!rev.comment && typeof rev.commenthidden === 'string') {
				return '(خلاصهٔ پنهان‌شده)';
			}
			return '«' + rev.comment + '»';

		};

		var orig;
		if (data.length) {
			var sha1 = data[0].sha1;
			for (var i = 1; i < data.length; ++i) {
				if (data[i].sha1 === sha1) {
					orig = data[i];
					break;
				}
			}

			if (!orig) {
				orig = data[0];
			}
		}

		var origtext = '';
		if (orig) {
			origtext = '{{تفاوت۲|' + orig.revid + '|' + orig.timestamp + '}} ' + hasHiddenComment(orig);
		}

		var grouped_diffs = {};

		var parentid, lastid;
		for (var j = 0; j < params.diffs.length; ++j) {
			var cur = params.diffs[j];
			if ((cur.revid && cur.revid !== parentid) || lastid === null) {
				lastid = cur.revid;
				grouped_diffs[lastid] = [];
			}
			parentid = cur.parentid;
			grouped_diffs[lastid].push(cur);
		}

		var difftext = $.map(grouped_diffs, function(sub) {
			var ret = '';
			if (sub.length >= 2) {
				var last = sub[0];
				var first = sub.slice(-1)[0];
				var label = 'ویرایش‌های سازندهٔ انجام‌شده از ' + new Morebits.date(first.timestamp).format('HH:mm, D MMMM YYYY', 'utc') + ' (UTC) تا ' + new Morebits.date(last.timestamp).format('HH:mm, D MMMM YYYY', 'utc') + ' (UTC)';
				ret = '# {{تفاوت|شناسه قدیمی=' + first.parentid + '|شناسه جدیدتر=' + last.revid + '|برچسب=' + label + '}}\n';
			}
			ret += sub.reverse().map(function(v) {
				return (sub.length >= 2 ? '#' : '') + '# {{تفاوت۲|' + v.revid + '|' + new Morebits.date(v.timestamp).format('HH:mm, D MMMM YYYY', 'utc') + ' (UTC)}} ' + hasHiddenComment(v);
			}).join('\n');
			return ret;
		}).reverse().join('\n');
		var warningtext = params.warnings.reverse().map(function(v) {
			return '# ' + ' {{تفاوت۲|' + v.revid + '|' + new Morebits.date(v.timestamp).format('HH:mm, D MMMM YYYY', 'utc') + ' (UTC)}} ' + hasHiddenComment(v);
		}).join('\n');
		var resolvetext = params.resolves.reverse().map(function(v) {
			return '# ' + ' {{تفاوت۲|' + v.revid + '|' + new Morebits.date(v.timestamp).format('HH:mm, D MMMM YYYY', 'utc') + ' (UTC)}} ' + hasHiddenComment(v);
		}).join('\n');

		if (params.free_resolves) {
			var page = params.free_resolves;
			if (page.compare) {
				resolvetext += '\n# ' + ' {{تفاوت|شناسه قدیمی=' + page.compare.fromrevid + '|شناسه جدیدتر=' + page.compare.torevid + '|برچسب=ویرایش‌های سازنده در ' + page.compare.totitle + '}}';
			} else if (page.revisions) {
				var revCount = page.revisions.length;
				var rev;
				if (revCount < 3) { // diff=prev or next
					rev = revCount === 1 ? page.revisions[0] : page.revisions[1];
					resolvetext += '\n# ' + ' {{تفاوت۲|' + rev.revid + '|' + new Morebits.date(rev.timestamp).format('HH:mm, D MMMM YYYY', 'utc') + ' (UTC) در ' + page.title + '}} ' + hasHiddenComment(rev);
				} else { // diff and oldid are nonconsecutive
					rev = page.revisions[0];
					var revLatest = page.revisions[revCount - 1];
					var label = 'ویرایش‌های سازندهٔ انجام‌شده از ' + new Morebits.date(rev.timestamp).format('HH:mm, D MMMM YYYY', 'utc') + ' (UTC) تا ' + new Morebits.date(revLatest.timestamp).format('HH:mm, D MMMM YYYY', 'utc') + ' (UTC) در ' + page.title;
					resolvetext += '\n# {{تفاوت|شناسه قدیمی=' + rev.revid + '|شناسه جدیدتر=' + revLatest.revid + '|برچسب=' + label + '}}\n';
				}
			}
		}

		var comment = params.comment.replace(/~*$/g, '').trim();

		if (comment) {
			comment += ' ~~~~';
		}

		var text = '\n\n' + '{{جا:گزارش تام۳|تفاوت‌ها=' + difftext + '|هشدارها=' + warningtext + '|حل اختلاف=' + resolvetext + '|نام صفحه=' + params.page + '|اولیه=' + origtext + '|توضیحات=' + comment + '|کاربر=' + params.uid + '}}';

		var reportpage = 'ویکی‌پدیا:تابلوی اعلانات مدیران/نقض ۳ برگردان';

		Morebits.wiki.actionCompleted.redirect = reportpage;
		Morebits.wiki.actionCompleted.notice = 'گزارش کردن کامل شد';

		var an3Page = new Morebits.wiki.page(reportpage, 'در حال واکشی صفحهٔ بحث');
		an3Page.setFollowRedirect(true);
		an3Page.setEditSummary('افزودن گزارش جدید برای [[ویژه:مشارکت‌ها/' + params.uid + '|' + params.uid + ']].');
		an3Page.setChangeTags(Twinkle.changeTags);
		an3Page.setAppendText(text);
		an3Page.append();

		// notify user

		var notifyText = '\n\n{{جا:آگاه‌سازی تام۳|1=' + mw.util.wikiUrlencode(params.uid) + '|خودکار=1}} ~~~~';

		var talkPage = new Morebits.wiki.page('بحث کاربر:' + params.uid, 'در حال آگاه‌سازی کاربر دخیل در جنگ ویرایشی');
		talkPage.setFollowRedirect(true);
		talkPage.setEditSummary('آگاه‌سازی از بحث در تابلوی اعلانات جنگ ویرایشی.');
		talkPage.setChangeTags(Twinkle.changeTags);
		talkPage.setAppendText(notifyText);
		talkPage.append();
		Morebits.wiki.removeCheckpoint();  // all page updates have been started
	}).fail(function(data) {
		console.log('API failed :(', data); // eslint-disable-line no-console
	});
};

Twinkle.addInitCallback(Twinkle.arv, 'arv');
})(jQuery);


// </nowiki>