Jump to content

User:DreamRimmer/SBRequest-enwiki.js

From Wikipedia, the free encyclopedia
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
//<nowiki>
mw.loader.using(['mediawiki.api', 'mediawiki.util', 'oojs-ui'], function () {
	'use strict';
	const page = mw.config.get('wgPageName');
	const api = new mw.Api();
	let token = null;
	async function getToken() {
		try {
			const res = await api.get({
				action: 'query',
				meta: 'tokens',
				type: 'csrf'
			});
			token = res.query.tokens.csrftoken;
		} catch (e) {
			console.error('Error getting token:', e);
			throw e;
		}
	}
	function ItemInputWidget() {
		OO.ui.Widget.call(this);
		this.textInput = new OO.ui.TextInputWidget({
			placeholder: 'Enter item',
			required: true,
			rows: 1
		});
		this.dropdown = new OO.ui.DropdownInputWidget({
			options: [
				{ data: 'link', label: 'URL' },
				{ data: 'ip', label: 'IP' },
				{ data: 'user', label: 'User' }
			],
			value: 'link'
		});
		this.textInput.$element.css('width', '67%');
		this.dropdown.$element.css('width', '30%');
		this.layout = new OO.ui.HorizontalLayout({
			items: [ this.textInput, this.dropdown ]
		});
		this.$element.addClass('itemInputWidget').css('margin-bottom', '5px');
		this.$element.append(this.layout.$element);
	}
	OO.inheritClass(ItemInputWidget, OO.ui.Widget);
	function createItemField() {
		return new ItemInputWidget();
	}
	function RequestDialog(config) {
		RequestDialog.super.call(this, config);
	}
	OO.inheritClass(RequestDialog, OO.ui.ProcessDialog);
	RequestDialog.static.name = 'requestDialog';
	RequestDialog.static.title = 'SBRequest';
	RequestDialog.static.actions = [
		{ action: 'accept', label: 'Submit', flags: ['primary', 'progressive'] },
		{ action: 'cancel', label: 'Cancel', flags: 'safe' }
	];
	RequestDialog.prototype.initialize = function () {
		RequestDialog.super.prototype.initialize.apply(this, arguments);
		this.itemContainer = new OO.ui.FieldsetLayout({
			label: 'Blacklist items:'
		});
		this.itemContainer.addItems([ createItemField() ]);
		this.reasonInput = new OO.ui.MultilineTextInputWidget({
			placeholder: 'Reason for blacklist',
			multiline: true,
			required: true,
			rows: 2
		});
		const addButton = new OO.ui.ButtonWidget({
			label: '+',
			flags: ['progressive']
		});
		addButton.on('click', () => {
			this.itemContainer.addItems([ createItemField() ]);
			this.updateSize();
		});
		this.content = new OO.ui.PanelLayout({ padded: true, expanded: false });
		this.content.$element.append(
			new OO.ui.FieldsetLayout({
				items: [
					this.itemContainer,
					new OO.ui.FieldLayout(addButton),
					new OO.ui.FieldLayout(this.reasonInput, { label: 'Reason:', align: 'top' })
				]
			}).$element
		);
		this.$body.append(this.content.$element);
	};
	RequestDialog.prototype.getBodyHeight = function () {
		return this.content.$element.outerHeight(true) + 20;
	};
	RequestDialog.prototype.getActionProcess = function (action) {
		if (action === 'accept') {
			return new OO.ui.Process(async () => {
				const items = this.itemContainer.items.map(widget => {
					return {
						value: widget.textInput.getValue(),
						type: widget.dropdown.getValue()
					};
				}).filter(item => item.value);
				const reason = this.reasonInput.getValue();
				if (items.length === 0) {
					alert('Please enter at least one item to be blacklisted.');
					return;
				}
				if (!reason) {
					alert('Please enter a reason for the blacklist.');
					return;
				}
				const signature = '~~~~';
				let report;
				if (items.length === 1) {
					const item = items[0];
					report = `== ${item.value} ==\n* {{${item.type === 'link' ? 'LinkSummary' : item.type === 'ip' ? 'ipsummary' : 'usersummary'}|${item.value}}}\n${reason} ${signature}\n`;
				} else {
					report = `== Bulk spam additions (${items[0].value} and more) ==\n`;
					items.forEach(item => {
						report += `* {{${item.type === 'link' ? 'LinkSummary' : item.type === 'ip' ? 'ipsummary' : 'usersummary'}|${item.value}}}\n`;
					});
					report += `${reason} ${signature}\n`;
				}
				const success = await appendReport(report);
				if (success) {
					alert('Request submitted successfully!');
					location.reload();
					this.close({ action: 'accept' });
				}
			});
		} else if (action === 'cancel') {
			return new OO.ui.Process(() => {
				this.close({ action: 'cancel' });
			});
		}
	};
	async function appendReport(report) {
		if (!token) await getToken();
		const res = await api.get({
			action: 'query',
			prop: 'revisions',
			titles: page,
			rvprop: 'content',
			format: 'json'
		});
		const pages = res.query.pages;
		const data = pages[Object.keys(pages)[0]];
		let content = data.revisions[0]['*'];
		const headingRegex = /^=[^=]+=$/gm;
		const headings = [...content.matchAll(headingRegex)];
		const proposedAdditionsIndex = headings.findIndex(h => /^=\s*proposed additions\s*=$/i.test(h[0]));
		if (proposedAdditionsIndex === -1) {
			alert('Could not find the "Proposed additions" section.');
			return false;
		}
		const removalsHeading = headings.find(h => /^=\s*proposed removals\s*=$/i.test(h[0]));
		let insertPos;
		if (removalsHeading) {
			insertPos = removalsHeading.index;
		} else {
			insertPos = content.length;
		}
		const newContent = content.substring(0, insertPos) + report + '\n' + content.substring(insertPos);
		await api.postWithToken('csrf', {
			action: 'edit',
			title: page,
			text: newContent,
			summary: 'Requesting additions (using [[User:DreamRimmer/SBRequest-enwiki.js|SBRequest-enwiki.js]])',
			format: 'json'
		});
		return true;
	}
	async function init() {
		if (page === 'MediaWiki_talk:Spam-blacklist') {
			const button = document.createElement('button');
			button.id = 'request-addition-button';
			button.className = 'oo-ui-buttonElement oo-ui-buttonElement-progressive oo-ui-widget oo-ui-widget-enabled';
			button.style = 'margin: 10px auto;background-color: rgb(51, 102, 204);color: white;border: 1px solid rgb(51, 102, 204);text-align: center;border-radius: 3px;font-size: 18px;padding: 8px 15px;display: block;font-weight: bold;cursor: pointer;';
			button.textContent = 'Request addition';
			document.querySelector('table[role="presentation"]').insertAdjacentElement('afterend', button);
			button.addEventListener('click', function (e) {
				e.preventDefault();
				const windowManager = new OO.ui.WindowManager();
				$(document.body).append(windowManager.$element);
				const requestDialog = new RequestDialog({ size: 'medium' });
				windowManager.addWindows([requestDialog]);
				windowManager.openWindow(requestDialog);
			});
		}
	}
	init();
});
//</nowiki>