User:JJPMaster/d-batch.js

importScript( 'User:JJPMaster/d-batch/links.js' ); // Backlink: [[User:JJPMaster/d-batch/links.js]]
importScript( 'User:JJPMaster/d-batch/cat.js' ); // Backlink: [[User:JJPMaster/d-batch/cat.js]]
importScript( 'User:JJPMaster/d-batch/prefix.js' ); // Backlink: [[User:JJPMaster/d-batch/prefix.js]]

async function getSubpages(page) {
	var params = {
		action: 'query',
		list: 'allpages',
		apprefix: `${new mw.Title(page).getMain()}/`,
		apnamespace: new mw.Title(page).getNamespaceId(),
		aplimit: 'max',
		format: 'json'
	},
	api = new mw.Api();
	try {
		const data = await api.get(params);
		return data.query.allpages.map(i => i.title);
	}
	catch {
		console.log("No subpages of " + page);
		return [];
	}
}

async function getRedirects(page) {
	var params = {
		action: 'query',
		prop: 'redirects',
		titles: page,
		rdprop: 'title',
		rdlimit: 'max',
		format: 'json'
	},
	api = new mw.Api();
	try {
		const data = await api.get(params);
		return Object.values(data.query.pages)[0].redirects.map(i => i.title);
	}
	catch {
		console.log("No subpages of " + page);
		return [];
	}
}

async function deleteBatch(arr) {
	let newList = arr.map(item => `<li><a href="/wiki/${item.replace(/ /g, "_")}">${item}</a></li>`);
	if (newList.length == 0) {
		alert("Luna: There are no pages to delete.");
		return;
	}
	$("#bodyContent").append(`
		<div id="dBatchDialog">
		You are about to delete the following ${newList.length} pages:\n<ol>${newList.join("\n")}</ol>Are you sure you want to do this?<br/>
		<textarea id="dBatchReason" name="dBatchReason" placeholder="Reason for deletion ('$title' will be replaced by the respective page's title)"></textarea>	
		<input type="checkbox" id="deleteTalk" name="deleteTalk" /><label for="deleteTalk">Delete associated talk pages</label><br/>
		<input type="checkbox" id="deleteSubs" name="deleteSubs" /><label for="deleteSubs">Delete subpages</label><br/>
		<input type="checkbox" id="deleteReds" name="deleteReds" /><label for="deleteReds">Delete redirects</label><br/>
		<button type="button" id="dBatchConfirm">Delete all pages</button>
		</div>`);
	$("#dBatchDialog").dialog({ title: "Batch delete", width: "auto", height: "auto" });

	$("#dBatchConfirm").click(async () => {
		let reason = document.getElementById("dBatchReason").value;
		if (!reason) {
			alert("You must provide a reason.");
			return;
		}

		let deletePromises = [];

		for (const p of arr) {
			let params = {
				action: 'delete',
				deletetalk: $("#deleteTalk").prop("checked"),
				title: p,
				reason: reason.replace(/\$[Tt]itle/gm, p),
				tags: "Luna",
				format: 'json'
			};
			let api = new mw.Api();
			console.log(`Deleting page: ${p}`);
			deletePromises.push(api.postWithToken('csrf', params));

			// Handle subpages
			if ($("#deleteSubs").prop("checked")) {
				try {
					let subpages = await getSubpages(p);
					console.log(`Found ${subpages.length} subpages for ${p}:`, subpages);
					for (const i of subpages) {
						let subParams = {
							action: 'delete',
							deletetalk: $("#deleteTalk").prop("checked"),
							title: i,
							reason: "Deleted together with the parent page with reason: " + reason.replace(/\$[Tt]itle/gm, p),
							tags: "Luna",
							format: 'json'
						};
						let subApi = new mw.Api();
						console.log(`Deleting subpage: ${i}`);
						deletePromises.push(subApi.postWithToken('csrf', subParams));
					}
				} catch (e) {
					console.log("There are no subpages of " + p);
				}
			}

			// Handle redirects
			if ($("#deleteReds").prop("checked")) {
				try {
					let redirects = await getRedirects(p);
					console.log(`Found ${redirects.length} redirects to ${p}:`, redirects);
					for (const i of redirects) {
						let redirParams = {
							action: 'delete',
							deletetalk: $("#deleteTalk").prop("checked"),
							title: i,
							reason: "Deleted together with the redirect target with reason: " + reason.replace(/\$[Tt]itle/gm, p),
							tags: "Luna",
							format: 'json'
						};
						let redirApi = new mw.Api();
						console.log(`Deleting redirect: ${i}`);
						deletePromises.push(redirApi.postWithToken('csrf', redirParams));
					}
				} catch (e) {
					console.log("There are no redirects to " + p);
				}
			}
		}
		console.log(deletePromises);
		await Promise.all(deletePromises);

		mw.notify("Luna:\nThe batch deletion has been completed.");
		console.log("All deletions completed.");
		setTimeout(() => window.location.reload(), 2000);
	});
}