Usuario:Nacaru/tests.js

De Wikipedia, la enciclopedia libre

Nota: Después de guardar, debes refrescar la caché de tu navegador para ver los cambios. Internet Explorer: mantén presionada Ctrl mientras pulsas Actualizar. Firefox: mientras presionas Mayús pulsas el botón Actualizar, (o presiona Ctrl-Shift-R). Los usuarios de Google Chrome y Safari pueden simplemente pulsar el botón Recargar. Para más detalles e instrucciones acerca de otros exploradores, véase Ayuda:Cómo limpiar la caché.

//<nowiki>
/******/ (() => { // webpackBootstrap
/******/ 	"use strict";
var __webpack_exports__ = {};

;// CONCATENATED MODULE: ./src/modules/utils.js
const currentPageName = mw.config.get('wgPageName');
const currentPageNameWithoutUnderscores = currentPageName.replaceAll('_', ' ');
const currentUser = mw.config.get('wgUserName');
const relevantUserName = mw.config.get("wgRelevantUserName");
const currentNamespace = mw.config.get('wgNamespaceNumber');
const currentAction = mw.config.get('wgAction');
const currentSkin = mw.config.get('skin');
const diffNewId = mw.config.get('wgDiffNewId');

// Returns the name of the main page from a string including the talk page in it
function cleansePageName(pageName) {
    if (pageName.startsWith("Discusión:")) {
        return pageName.substring("Discusión:".length);
    }
    return pageName
}

//Formats the window that holds the status messages
// It must receive a Morebits' simplewindow object as argument
function createStatusWindow(window) {
    window.setTitle('Procesando acciones');
    let statusdiv = document.createElement('div');
    statusdiv.style.padding = '15px';
    window.setContent(statusdiv);
    Morebits.status.init(statusdiv);
    window.display();
}

// Returns a promise with the name of the user who created the page
function getCreator() {
    let params = {
        action: 'query',
        prop: 'revisions',
        titles: cleansePageName(currentPageName),
        rvprop: 'user',
        rvdir: 'newer',
        format: 'json',
        rvlimit: 1,
    }
    let apiPromise = new mw.Api().get(params);
    let userPromise = apiPromise.then(function (data) {
        let pages = data.query.pages;
        for (let p in pages) {
            return pages[p].revisions[0].user;
        }
    });

    return userPromise;
}

// Returns a boolean stating whether there's a spot available to create the page (true) or whether it already exists (false)
function isPageMissing(title) {
    let params = {
        action: 'query',
        titles: title,
        prop: 'pageprops',
        format: 'json'
    };
    let apiPromise = new mw.Api().get(params);
    return apiPromise.then(function (data) {
        let result = data.query.pages
        return result.hasOwnProperty("-1")
    });
}

// Returns the protection status of the page as a string through a query to the mw API
function getProtectionStatus(pageName) {
    let params = {
        action: 'query',
        prop: 'info',
        inprop: 'protection',
        titles: pageName,
        format: 'json',
    }
    let apiPromise = new mw.Api().get(params);
    return apiPromise.then((data) => {
        let pages = data.query.pages;
        let object = {};
        object.level = 'sin protección'
        for (let p in pages) {
            for (let info of pages[p].protection) {
                console.log(info.type);
                if (info?.type == 'move') {
                    continue;
                } else {
                    const protectionLevel = info?.level;
                    switch (protectionLevel) {
                        case 'sysop':
                            object.level = 'solo bibliotecarios';
                            break;
                        case 'autoconfirmed':
                            object.level = 'solo usuarios autoconfirmados';
                            break;
                        case 'templateeditor':
                            object.level = 'solo editores de plantillas';
                            break;
                    }
                    if (info?.expiry) {
                        const expiryTimeStamp = pages[p].protection[0]?.expiry;
                        object.expiry = expiryTimeStamp;
                    }
                }
            }
        }
        return object;
    });
}

// Get the text content of a page as a string
function getContent(pageName) {
    let params = {
        action: 'query',
        prop: 'revisions',
        titles: pageName,
        rvprop: 'content',
        rvslots: 'main',
        formatversion: '2',
        format: 'json'
    }

    let apiPromise = new mw.Api().get(params).then(
        ((data) => {
            return data.query.pages[0].revisions[0].slots?.main?.content
        })
    );

    return apiPromise

}

function parseTimeStamp(timeStamp) {
    const options = {
        year: 'numeric',
        month: 'long',
        day: 'numeric',
    }
    const date = new Date(timeStamp);
    return date.toLocaleDateString('es-ES', options)
}
;// CONCATENATED MODULE: ./src/modules/deletionrequestmaker.js


// Declaring the variable that will eventually hold the form window now will allow us to manipulate it more easily  later
let deletionrequestmaker_Window;

// This is the dictionary holding the options for the categories deletion requests can be classified as
let listOptions = [
    { code: 'B', name: 'Biografías' },
    { code: 'CAT', name: 'Categorías' },
    { code: 'D', name: 'Deportes y juegos' },
    { code: 'F', name: 'Ficción y artes' },
    { code: 'I', name: 'Inclasificables' },
    { code: 'L', name: 'Lugares y transportes' },
    { code: 'M', name: 'Música y medios de comunicación' },
    { code: 'N', name: 'Consultas sin clasificar todavía' },
    { code: 'O', name: 'Organizaciones, empresas y productos' },
    { code: 'P', name: 'Plantillas y userboxes' },
    { code: 'S', name: 'Sociedad' },
    { code: 'T', name: 'Ciencia y tecnología' },
    { code: 'W', name: 'Web e internet' }
];

// This function will take the options from the options dictionary and assign them keys that morebits can recognise
function getCategoryOptions() {
    let categoryOptions = [];
    for (let category of listOptions) {
        let option = { type: 'option', value: category.code, label: category.name };
        categoryOptions.push(option);
    }
    return categoryOptions;
}

//Creates the window for the form that will later be filled with the pertinent info
function createFormWindow() {
    deletionrequestmaker_Window = new Morebits.simpleWindow(620, 530);
    deletionrequestmaker_Window.setScriptName('Twinkle Lite');
    deletionrequestmaker_Window.setTitle('Consulta de borrado');
    deletionrequestmaker_Window.addFooterLink('Política de consultas de borrado', 'Wikipedia:Consultas de borrado mediante argumentación');
    let form = new Morebits.quickForm(submitMessage);
    form.append({
        type: 'textarea',
        name: 'reason',
        label: 'Describe el motivo:',
        tooltip: 'Puedes usar wikicódigo en tu descripción, tu firma se añadirá automáticamente.'
    });
    form.append({
        type: 'submit',
        label: 'Aceptar'
    });

    let categoryField = form.append({
        type: 'field',
        label: 'Categorías:',
    })

    categoryField.append({
        type: 'select',
        name: 'category',
        label: 'Selecciona la categoría de la página:',
        list: getCategoryOptions()
    });

    form.append({
        type: 'checkbox',
        list:
            [{
                name: "notify",
                value: "notify",
                label: "Notificar al creador de la página",
                checked: true,
                tooltip: "Marca esta casilla para que Twinkle Lite deje un mensaje automático en la página de discusión del creador advirtiéndole del posible borrado de su artículo"
            }],
        style: "padding-left: 1em;"
    })

    form.append({
        type: 'checkbox',
        list:
            [{
                name: "otherArticles",
                value: "otherArticles",
                label: "Aplicar la CDB a más artículos",
                checked: false,
            }],
        style: "padding-left: 1em; padding-bottom:0.5em;",
        event: (e) => {
            // Morebits' buttons value is in English by default and there is no other way to translate the text that doesn't involve DOM manipulation
            // This fuction will find those values and translate them into Spanish
            const checked = e.target.checked;
            const box = document.getElementById('otherArticleFieldBox');
            if (checked) {
                box.style.display = '';
                const boxAddButton = document.querySelector('input[value="more"]');
                if (boxAddButton) {
                    boxAddButton.value = "añadir";
                    boxAddButton.style.marginTop = '0.3em';
                    boxAddButton.addEventListener('click', () => {
                        const boxRemoveButton = document.querySelector('input[value="remove"]');
                        if (boxRemoveButton) {
                            boxRemoveButton.value = "eliminar";
                            boxRemoveButton.style.marginLeft = '0.3em';
                        }
                    })
                }
            } else {
                box.style.display = 'none';
            }
        }
    })

    form.append({
        type: 'dyninput',
        label: 'Otros artículos a los que aplicar la consulta:',
        sublabel: 'Artículo:',
        name: 'otherArticleFieldBox',
        style: "display: none;",
        id: 'otherArticleFieldBox',
        tooltip: 'Escribe el nombre del artículo sin ningún tipo de wikicódigo'
    })

    let result = form.render();
    deletionrequestmaker_Window.setContent(result);
    deletionrequestmaker_Window.display();
}

function submitMessage(e) {
    let form = e.target;
    let input = Morebits.quickForm.getInputData(form);
    if (input.reason === ``) {
        alert("No se ha establecido un motivo.");
    } else {
        if (window.confirm(`Esto creará una consulta de borrado para el artículo ${currentPageNameWithoutUnderscores}, ¿estás seguro?`)) {
            let statusWindow = new Morebits.simpleWindow(400, 350);
            createStatusWindow(statusWindow);
            new Morebits.status("Paso 1", "comprobando disponibilidad y creando la página de discusión de la consulta de borrado...", "info");
            createDeletionRequestPage(input.category, input.reason)
                .then(function () {
                    new Morebits.status("Paso 2", "colocando plantilla en la(s) página(s) nominada(s)...", "info");
                    return new mw.Api().edit(
                        currentPageName,
                        buildEditOnNominatedPage
                    )
                })
                .then(function () {
                    if (input.otherArticleFieldBox) {
                        const otherArticleArray = Array.from(document.querySelectorAll('input[name="otherArticleFieldBox"]')).map((o) => o.value);
                        for (let article of otherArticleArray) {
                            makeEditOnOtherNominatedPages(article);
                        }
                    }
                })
                .then(function () {
                    if (!input.notify) return;
                    new Morebits.status("Paso 3", "publicando un mensaje en la página de discusión del creador...", "info");
                    return getCreator().then(postsMessage);
                })
                .then(function () {
                    new Morebits.status("✔️ Finalizado", "actualizando página...", "status");
                    setTimeout(() => { location.reload() }, 2000);
                })
                .catch(function (error) {
                    new Morebits.status("❌ Se ha producido un error", "Comprueba las ediciones realizadas", "error");
                    console.log(`Error: ${error}`);
                })
        }
    }
}

async function makeEditOnOtherNominatedPages(article) {
    await new mw.Api().edit(
        article,
        function (revision) {
            return {
                text: `{{sust:cdb|${currentPageName}}}\n` + revision.content,
                summary: `Nominada para su borrado, véase [[Wikipedia:Consultas de borrado/${currentPageName}]] mediante [[WP:Twinkle Lite|Twinkle Lite]]`,
                minor: false
            }
        }
    )
}

// function that builds the text to be inserted in the new DR page.
function buildDeletionTemplate(category, reason) {
    return `{{sust:cdb2|pg={{sust:SUBPAGENAME}}|cat=${category}|texto=${reason}|{{sust:CURRENTDAY}}|{{sust:CURRENTMONTHNAME}}}} ~~~~`
}

//function that fetches the two functions above and actually adds the text to the article to be submitted to DR.
function buildEditOnNominatedPage(revision) {
    return {
        text: '{{sust:cdb}}\n' + revision.content,
        summary: `Nominada para su borrado, véase [[Wikipedia:Consultas de borrado/${currentPageName}]] mediante [[WP:Twinkle Lite|Twinkle Lite]]`,
        minor: false
    };
}

//function that creates the page hosting the deletion request
function createDeletionRequestPage(category, reason) {
    return isPageMissing(`Wikipedia:Consultas de borrado/${currentPageName}`)
        .then((isPageMissing) => {
            if (isPageMissing) {
                return new mw.Api().create(`Wikipedia:Consultas de borrado/${currentPageName}`,
                    { summary: `Creando página de discusión para el borrado de [[${currentPageNameWithoutUnderscores}]] mediante [[WP:Twinkle Lite|Twinkle Lite]]` },
                    buildDeletionTemplate(category, reason)
                );
            } else {
                getContent(`Wikipedia:Consultas de borrado/${currentPageName}`).then((content) => {
                    if (content.includes('{{archivo borrar cabecera') || content.includes('{{cierracdb-arr}}')) {
                        if (confirm(`Parece que ya se había creado una consulta de borrado para ${currentPageNameWithoutUnderscores} cuyo resultado fue MANTENER. ¿Quieres abrir una segunda consulta?`)) {
                            return new mw.Api().create(
                                `Wikipedia:Consultas de borrado/${currentPageName}_(segunda_consulta)`,
                                { summary: `Creando página de discusión para el borrado de [[${currentPageNameWithoutUnderscores}]] mediante [[WP:Twinkle Lite|Twinkle Lite]]` },
                                buildDeletionTemplate(category, reason))
                        } else {
                            new Morebits.status("Proceso interrumpido", "acción abortada por el usuario... actualizando página", "error")
                            setTimeout(() => { location.reload() }, 4000);
                        }
                    } else {
                        alert('Parece que ya existe una consulta en curso')
                        new Morebits.status("Proceso interrumpido", "ya existe una consulta en curso", "error");
                        setTimeout(() => { location.reload() }, 4000);
                    }
                })
            }
        })

}

// Leaves a message on the creator's talk page, if the page has not been created yet, it will do that
function postsMessage(creator) {
    return isPageMissing(`Usuario_discusión:${creator}`)
        .then(function (mustCreateNewTalkPage) {
            if (mustCreateNewTalkPage) {
                return new mw.Api().create(
                    `Usuario_discusión:${creator}`,
                    { summary: 'Aviso al usuario de la apertura de una CDB mediante [[WP:Twinkle Lite|Twinkle Lite]]' },
                    `{{sust:Aviso cdb|${currentPageNameWithoutUnderscores}}} ~~~~`
                );
            } else {
                return new mw.Api().edit(
                    `Usuario_discusión:${creator}`,
                    function (revision) {
                        return {
                            text: revision.content + `\n{{sust:Aviso cdb|${currentPageNameWithoutUnderscores}}} ~~~~`,
                            summary: 'Aviso al usuario de la apertura de una CDB mediante [[WP:Twinkle Lite|Twinkle Lite]]',
                            minor: false
                        }
                    }
                )
            }
        })
}


;// CONCATENATED MODULE: ./src/modules/pageprotection.js


let pageprotection_Window;

let listProtectionOptions = [
	{ code: "protección", name: "Solicitar protección", default: true },
	{ code: "desprotección", name: "Solicitar desprotección" }
]

function getProtectionTypeOptions() {
	let dropDownOptions = [];
	for (let chosenType of listProtectionOptions) {
		let option = { type: 'option', value: chosenType.code, label: chosenType.name, checked: chosenType.default };
		dropDownOptions.push(option);
	}
	return dropDownOptions;
}

let listMotiveOptions = [
	{ name: "Vandalismo" },
	{ name: "SPAM" },
	{ name: "Información falsa o especulativa" },
	{ name: "Guerra de ediciones" },
	{ name: "Otro" }
]

function getMotiveOptions() {
	let dropDownOptions = [];
	for (let motive of listMotiveOptions) {
		let option = { type: 'option', value: motive.name, label: motive.name, checked: motive.default };
		dropDownOptions.push(option);
	}
	return dropDownOptions
}

function protectionTextBuilder(protectionExpiry) {
	switch (protectionExpiry) {
		case undefined:
			return ''
		case 'infinity':
			return '(protegido para siempre)'
		default:
			return `(hasta el ${parseTimeStamp(protectionExpiry)})`
	}
}


function pageprotection_createFormWindow() {
	pageprotection_Window = new Morebits.simpleWindow(620, 530);
	pageprotection_Window.setScriptName('Twinkle Lite');
	pageprotection_Window.setTitle('Solicitar protección de la página');
	pageprotection_Window.addFooterLink('Política de protección', 'Wikipedia:Política de protección');
	let form = new Morebits.quickForm(pageprotection_submitMessage);

	let radioField = form.append({
		type: 'field',
		label: 'Tipo:',
	});

	radioField.append({
		type: 'radio',
		name: 'protection',
		id: 'protect',
		event:
			function (e) {
				let nameToModify = document.querySelector("select[name='motive']")
				if (e.target.value !== "protección") {
					nameToModify.setAttribute('disabled', "")
				} else {
					nameToModify.removeAttribute('disabled', "")
				}
			},
		list: getProtectionTypeOptions()
	})

	form.append({
		type: 'div',
		name: 'currentProtection',
		label: `Nivel actual de protección: `,
	})

	let textAreaAndReasonField = form.append({
		type: 'field',
		label: 'Opciones:',
	});

	textAreaAndReasonField.append({
		type: 'select',
		name: 'motive',
		label: 'Selecciona el motivo:',
		list: getMotiveOptions(),
		disabled: false
	});

	textAreaAndReasonField.append({
		type: 'textarea',
		name: 'reason',
		label: 'Desarrolla la razón:',
		tooltip: 'Si no se rellena este campo, se utilizará como razón la seleccionada en la lista de motivos (si no se ha seleccionado «otro»). Puedes usar wikicódigo en tu descripción, tu firma se añadirá automáticamente.'
	});
	form.append({
		type: 'submit',
		label: 'Aceptar'
	});

	let result = form.render();
	pageprotection_Window.setContent(result);
	pageprotection_Window.display();

	getProtectionStatus(currentPageName).then(function (protection) {
		// Displays protection level on page
		const showProtection = document.querySelector("div[name='currentProtection'] > span.quickformDescription");
		showProtection.innerHTML = `Nivel actual de protección:<span style="color:royalblue; font-weight: bold;"> ${protection.level} <span style="font-weight: normal;">${protectionTextBuilder(protection.expiry)}</span>`;
		// Disables "unprotect" option if not applicable
		if (protection.level == 'sin protección') {
			let unprotectDiv = document.getElementById('protect').childNodes[1]
			unprotectDiv.firstChild.setAttribute('disabled', '');
		}

	})
}

function pageprotection_submitMessage(e) {
	let form = e.target;
	let input = Morebits.quickForm.getInputData(form);
	if (input.motive == 'Otro' && !input.reason) {
		alert("Se ha seleccionado «Otro» como motivo pero no se ha establecido un motivo.");
	} else {
		let statusWindow = new Morebits.simpleWindow(400, 350);
		createStatusWindow(statusWindow);
		new Morebits.status("Paso 1", `solicitando la ${input.protection} de la página...`, "info");
		new mw.Api().edit(
			"Wikipedia:Tablón_de_anuncios_de_los_bibliotecarios/Portal/Archivo/Protección_de_artículos/Actual",
			buildEditOnNoticeboard(input)
		)
			.then(function () {
				new Morebits.status("✔️ Finalizado", "cerrando ventana...", "status");
				setTimeout(() => {
					statusWindow.close();
					pageprotection_Window.close();
				}, 2500);
			})
			.catch(function (error) {
				new Morebits.status("❌ Se ha producido un error", "Comprueba las ediciones realizadas", "error");
				console.log(`Error: ${error}`);
			})

	}
}

function buildEditOnNoticeboard(input) {
	let title = `== ${input.protection == "desprotección" ? 'Solicitud de desprotección de ' : ''}[[${currentPageNameWithoutUnderscores}]] ==`;
	return (revision) => {
		return {
			text: revision.content + `\n
${title} 
;Artículo(s) 
* {{a|${currentPageNameWithoutUnderscores}}}
;Causa 
${input.reason ? input.reason : input.motive}
; Usuario que lo solicita
* ~~~~ 
;Respuesta
(a rellenar por un bibliotecario)`,
			summary: `Solicitando ${input.protection} de [[${currentPageNameWithoutUnderscores}]] mediante [[WP:Twinkle Lite|Twinkle Lite]]`,
			minor: false
		}
	}
}



;// CONCATENATED MODULE: ./src/modules/speedydeletion.js


let speedydeletion_Window, deletionTemplateExists;

let criteriaLists = {
    general: [
        { code: "g1", name: "G1. Vandalismo" },
        { code: "g2", name: "G2. Faltas de etiqueta" },
        { code: "g3", name: "G3. Páginas promocionales" },
        { code: "g4", name: "G4. Páginas de pruebas de edición" },
        { code: "g5", name: "G5. Bulos, fraudes" },
        { code: "g6", name: "G6. Violaciones de derechos de autor" },
        { code: "g7", name: "G7. Páginas de discusión huérfanas" },
        { code: "g8", name: "G8. Borrado de una página para dejar sitio" },
        { code: "g9", name: "G9. Recreación de material borrado" },
        { code: "g10", name: "G10. Para mantenimiento elemental" },
        { code: "g11", name: "G11. A petición del único autor" }
    ], articles: [
        {
            code: "a1", name: "A1. Viola «lo que Wikipedia no es»", subgroup: {
                type: 'checkbox',
                name: 'subA',
                list: [
                    { value: "a1.1", label: "A1.1 Artículos que solo incluyen enlaces" },
                    { value: "a1.2", label: "A1.2 Definiciones de diccionario o recetas" },
                    { value: "a1.3", label: "A1.3 Fuente primaria" },
                    { value: "a1.4", label: "A1.4 Ensayos de opinión" }
                ]
            },
        },
        { code: "a2", name: "A2. Infraesbozo" },
        { code: "a3", name: "A3. Páginas sin traducir o traducciones automáticas" },
        { code: "a4", name: "A4. Contenido no enciclopédico o sin relevancia" },
        {
            code: "a5", name: "A5. Artículo duplicado", subgroup: {
                type: "input",
                name: "originalArticleName",
                label: "Nombre del artículo original: ",
                tooltip: "Escribe el nombre del artículo sin utilizar wikicódigo. Ej.: «Granada (fruta)», «Ensalada» o «Plantilla:Atajos»",
                required: true
            }
        }
    ], redirects: [
        { code: "r1", name: "R1. Redirecciones a páginas inexistentes" },
        { code: "r2", name: "R2. Redirecciones de un espacio de nombres a otro" },
        { code: "r3", name: "R3. Redirecciones automáticas innecesarias" },
        { code: "r4", name: "R4. Redirecciones incorrectas o innecesarias" },
    ], categories: [
        { code: "c1", name: "C1. Categorías vacías" },
        { code: "c2", name: "C2. Categorías trasladadas o renombradas" },
        { code: "c3", name: "C3. Categorías que violan la política de categorías" }
    ], userpages: [
        { code: "u1", name: "U1. A petición del propio usuario" },
        { code: "u2", name: "U2. Usuario inexistente" },
        { code: "u3", name: "U3. Violación de la política de páginas de usuario" }
    ], templates: [
        { code: "p1", name: "P1. Violación de la política de plantillas de navegación" },
        { code: "p2", name: "P2. Subpágina de documentación huérfana" },
        { code: "p3", name: "P3. Plantillas de un solo uso" }
    ], other: [
        {
            code: "other", name: "Otra razón", subgroup: {
                type: "input",
                name: "otherreason",
                label: "Establece la razón: ",
                tooltip: "Puedes utilizar wikicódigo en tu respuesta",
                required: true
            }
        }
    ]
}

function getOptions(criteriaType) {
    let options = [];
    for (let chosenType of criteriaLists[criteriaType]) {
        let option = { value: chosenType.code, label: chosenType.name, checked: chosenType.default, subgroup: chosenType.subgroup };
        options.push(option);
    }
    return options;
}

async function speedydeletion_createFormWindow() {
    speedydeletion_Window = new Morebits.simpleWindow(620, 530);
    speedydeletion_Window.setScriptName('Twinkle Lite');
    speedydeletion_Window.setTitle('Solicitar borrado rápido');
    speedydeletion_Window.addFooterLink('Criterios para el borrado rápido', 'Wikipedia:Criterios para el borrado rápido');
    let form = new Morebits.quickForm(speedydeletion_submitMessage);

    form.append({
        type: 'checkbox',
        list:
            [{
                name: "notify",
                value: "notify",
                label: "Notificar al creador de la página",
                checked: true,
                tooltip: "Marca esta casilla para que Twinkle Lite deje un mensaje automático en la página de discusión del creador advirtiéndole del posible borrado de su artículo"
            }],
        style: "padding-left: 1em; padding-top:0.5em;"
    })

    let gField = form.append({
        type: 'field',
        label: 'Criterios generales:',
    });
    gField.append({
        type: 'checkbox',
        name: 'general',
        list: getOptions("general")
    })

    if (currentNamespace == 0 || currentNamespace == 104 && !mw.config.get('wgIsRedirect')) {
        let aField = form.append({
            type: 'field',
            label: 'Criterios para artículos y anexos:',
        })

        aField.append({
            type: 'checkbox',
            name: 'article',
            list: getOptions("articles")
        })
    }

    if (mw.config.get('wgIsRedirect')) {
        let rField = form.append({
            type: 'field',
            label: 'Criterios para páginas de redirección:',
        })
        rField.append({
            type: 'checkbox',
            name: 'redirect',
            list: getOptions("redirects")
        })
    }

    if (currentNamespace == 14) {
        let cField = form.append({
            type: 'field',
            label: 'Criterios para categorías:',
        })
        cField.append({
            type: 'checkbox',
            name: 'categories',
            list: getOptions("categories")
        })
    }

    if (currentNamespace == 2) {
        let uField = form.append({
            type: 'field',
            label: 'Criterios para páginas de usuario:',
        })
        uField.append({
            type: 'checkbox',
            name: 'userpages',
            list: getOptions("userpages")
        })
    }

    if (currentNamespace == 10) {
        let tField = form.append({
            type: 'field',
            label: 'Criterios para plantillas:',
        })
        tField.append({
            type: 'checkbox',
            name: 'templates',
            list: getOptions("templates")
        })
    }

    form.append({
        type: 'checkbox',
        name: 'other',
        list: getOptions("other"),
        style: "padding-left: 1em; padding-bottom: 0.5em"
    })

    form.append({
        type: 'submit',
        label: 'Aceptar'
    });

    let result = form.render();
    speedydeletion_Window.setContent(result);
    speedydeletion_Window.display();
    // After the content has been displayed, we will call the api
    // to check if a deletion template already exists and store
    // the info in a global variable
    deletionTemplateExists = await checkExistingDeletionTemplate();
}

function speedydeletion_submitMessage(e) {
    let form = e.target;
    let input = Morebits.quickForm.getInputData(form);
    //This little condition removes the A1 criterion if any of its subcriteria are included
    if (input?.subA) {
        if (input.subA.length > 0) {
            input.article.shift();
        }
    }
    // This will ask the user to confirm the action if there's a deletion template
    // in the article already, which is info we've previously stored as a global variable 
    if (deletionTemplateExists) {
        if (!confirm('Parece que ya existe una plantilla de borrado en el artículo, ¿deseas colocar la plantilla igualmente?')) {
            return
        }
    }
    let statusWindow = new Morebits.simpleWindow(400, 350);
    createStatusWindow(statusWindow);
    new Morebits.status("Paso 1", `generando plantilla de borrado...`, "info");
    new mw.Api().edit(
        currentPageName,
        speedyTemplateBuilder(input)
    )
        .then(function () {
            return getCreator().then(speedydeletion_postsMessage(input));
        })
        .then(function () {
            new Morebits.status("✔️ Finalizado", "actualizando página...", "status");
            setTimeout(() => { location.reload() }, 2000);
        })
        .catch(function (error) {
            new Morebits.status("❌ Se ha producido un error", "Comprueba las ediciones realizadas", "error")
            console.log(`Error: ${error}`);
        })
}

async function checkExistingDeletionTemplate() {
    const regex = /{{(?:sust\:)?(?:destruir|d|db-ul|db-user|speedy|borrar|db|delete|eliminar|aviso\sborrar)\|.+?}}/i
    const content = await getContent(currentPageName);
    if (content.match(regex)) {
        return true
    }
    return false
}

function speedyTemplateBuilder(data) {
    return (revision) => {
        return {
            text: `{{destruir|${allCriteria(data)}}} \n` + revision.content,
            summary: `Añadiendo plantilla de borrado mediante [[WP:Twinkle Lite|Twinkle Lite]]${data?.originalArticleName ? `. Artículo existente de mayor calidad: [[${data.originalArticleName}]]` : ''}`,
            minor: false
        }
    }
}

function allCriteria(data) {
    let fields = [];
    for (let criteriaType in data) {
        if (criteriaType !== "other" && Array.isArray(data[criteriaType])) {
            fields.push(...data[criteriaType]);
        }
    }

    let reasonString = data?.otherreason ?? '';
    if (reasonString != '') {
        fields.push(reasonString);
    }
    return fields.join('|');
}

function speedydeletion_postsMessage(input) {
    if (!input.notify) return;
    return (creator) => {
        if (creator == currentUser) {
            return;
        } else {
            new Morebits.status("Paso 2", "publicando un mensaje en la página de discusión del creador...", "info");
            return isPageMissing(`Usuario_discusión:${creator}`)
                .then(function (mustCreateNewTalkPage) {
                    if (mustCreateNewTalkPage) {
                        return new mw.Api().create(
                            `Usuario_discusión:${creator}`,
                            { summary: `Aviso al usuario del posible borrado de [[${currentPageNameWithoutUnderscores}]] mediante [[WP:Twinkle Lite|Twinkle Lite]]` },
                            `{{subst:Aviso destruir|${currentPageNameWithoutUnderscores}|${allCriteria(input)}}} ~~~~`
                        );
                    } else {
                        return new mw.Api().edit(
                            `Usuario_discusión:${creator}`,
                            function (revision) {
                                return {
                                    text: revision.content + `\n{{subst:Aviso destruir|${currentPageNameWithoutUnderscores}|${allCriteria(input)}}} ~~~~`,
                                    summary: `Aviso al usuario del posible borrado de [[${currentPageNameWithoutUnderscores}]] mediante [[WP:Twinkle Lite|Twinkle Lite]]`,
                                    minor: false
                                }
                            }
                        )
                    }
                })
        }
    }
}


;// CONCATENATED MODULE: ./src/modules/reports.js


let reportedUser;
let reports_Window;

let reports_listMotiveOptions = [
    { value: "CPP" },
    { value: "Cuenta creada para vandalizar" },
    { value: "Evasión de bloqueo" },
    { value: "Guerra de ediciones" },
    { value: "Nombre inapropiado" },
    { value: "Violación de etiqueta" },
    { value: "Vandalismo en curso" },
    { value: "Vandalismo persistente" },
    { value: "Otro" },
]

let motiveOptionsDict = {
    "CPP":
    {
        "link": "Wikipedia:Tablón_de_anuncios_de_los_bibliotecarios/Portal/Archivo/Nombres_inapropiados_y_vandalismo_persistente/Actual",
        "usersSubtitle": 'Lista de usuarios',
        "optionalReason": false
    },
    "Cuenta creada para vandalizar":
    {
        "link": "Wikipedia:Tablón_de_anuncios_de_los_bibliotecarios/Portal/Archivo/Nombres_inapropiados_y_vandalismo_persistente/Actual",
        "usersSubtitle": 'Lista de usuarios',
        "optionalReason": true
    },
    "Evasión de bloqueo":
    {
        "link": "Wikipedia:Tablón_de_anuncios_de_los_bibliotecarios/Portal/Archivo/Nombres_inapropiados_y_vandalismo_persistente/Actual",
        "usersSubtitle": 'Lista de usuarios',
        "optionalReason": false
    },
    "Guerra de ediciones":
    {
        "link": "Wikipedia:Tablón_de_anuncios_de_los_bibliotecarios/Portal/Archivo/3RR/Actual",
        "usersSubtitle": 'Usuarios implicados',
        "optionalReason": false
    },
    "Nombre inapropiado":
    {
        "link": "Wikipedia:Tablón_de_anuncios_de_los_bibliotecarios/Portal/Archivo/Nombres_inapropiados_y_vandalismo_persistente/Actual",
        "usersSubtitle": 'Lista de usuarios',
        "optionalReason": true
    },
    "Violación de etiqueta":
    {
        "link": "Wikipedia:Tablón_de_anuncios_de_los_bibliotecarios/Portal/Archivo/Violaciones_de_etiqueta/Actual",
        "usersSubtitle": 'Usuarios implicados',
        "optionalReason": false
    },
    "Vandalismo en curso":
    {
        "link": "Wikipedia:Vandalismo_en_curso",
        "optionalReason": false
    },
    "Vandalismo persistente":
    {
        "link": "Wikipedia:Tablón_de_anuncios_de_los_bibliotecarios/Portal/Archivo/Nombres_inapropiados_y_vandalismo_persistente/Actual",
        "usersSubtitle": 'Lista de usuarios',
        "optionalReason": true
    },
    "Otro":
    {
        "link": "Wikipedia:Tablón_de_anuncios_de_los_bibliotecarios/Portal/Archivo/Miscelánea/Actual",
        "usersSubtitle": 'Usuarios implicados',
        "optionalReason": false
    }
}

function reports_getMotiveOptions() {
    let dropDownOptions = [];
    for (let motive of reports_listMotiveOptions) {
        let option = { value: motive.value, label: motive.value, subgroup: motive.subgroup };
        dropDownOptions.push(option);
    }
    return dropDownOptions;
}

function reports_createFormWindow(reportedUserFromDOM) {

    // Something about the addPortletLink feature doesn't work well so this condition is unfortunately needed
    if (typeof reportedUserFromDOM == 'string') {
        reportedUser = reportedUserFromDOM;
    } else {
        reportedUser = relevantUserName;
    }

    reports_Window = new Morebits.simpleWindow(620, 530);
    reports_Window.setScriptName('Twinkle Lite');
    reports_Window.setTitle('Denunciar usuario');
    reports_Window.addFooterLink('Tablón de anuncios de los bibliotecarios', 'Wikipedia:Tablón de anuncios de los bibliotecarios');
    let form = new Morebits.quickForm(reports_submitMessage);

    let reportTypeField = form.append({
        type: 'field',
        label: 'Opciones:',
    })
    reportTypeField.append({
        type: 'select',
        label: 'Selecciona el motivo:',
        name: 'motive',
        list: reports_getMotiveOptions(),
        event:
            function (e) {
                let selectedOption = e.target.value
                document.querySelector("label[for='reasontextareanode']").innerText = `Desarrolla la razón${motiveOptionsDict[selectedOption].optionalReason ? ' (opcional)' : ''}:`
                document.getElementById('articlefieldnode').setAttribute('style', 'display:none');
                document.getElementById('otherreasonnode').setAttribute('style', 'display:none');
                switch (selectedOption) {
                    case 'Guerra de ediciones':
                        document.getElementById('articlefieldnode').removeAttribute('style');
                        changeButtonNames();
                        break;
                    case 'Violación de etiqueta':
                        document.querySelector("label[for='reasontextareanode']").innerText = 'Ediciones que constituyen una violación de etiqueta:'
                        break;
                    case 'Otro':
                        document.getElementById('otherreasonnode').removeAttribute('style')
                        break;
                }
            }
    })

    form.append({
        type: 'checkbox',
        list: [{
            name: "notify",
            value: "notify",
            label: "Notificar al usuario denunciado",
            checked: false,
            tooltip: "Marca esta casilla para que Twinkle Lite deje un mensaje automático en la página de discusión del usuario reportado avisándole de la denuncia"
        }],
        style: "padding-left: 1em;"
    })

    let reportInfoField = form.append({
        type: 'field',
        label: 'Información:'
    })
    reportInfoField.append({
        type: 'dyninput',
        label: 'Usuarios denunciados:',
        sublabel: 'Usuario:',
        name: 'usernamefield',
        value: "",
        tooltip: 'Escribe el nombre del usuario denunciado sin ningún tipo de wikicódigo'
    })
    reportInfoField.append({
        type: 'dyninput',
        label: 'Artículos involucrados:',
        sublabel: 'Artículo:',
        name: 'articlefieldbox',
        style: "display: none;",
        id: 'articlefieldnode',
        tooltip: 'Escribe el nombre del artículo sin ningún tipo de wikicódigo'
    })
    reportInfoField.append({
        type: "input",
        name: "otherreason",
        id: "otherreasonnode",
        style: "display: none;",
        placeholder: "Título de la denuncia",
    })

    reportInfoField.append({
        type: 'textarea',
        label: 'Desarrolla la razón:',
        name: 'reason',
        tooltip: 'Incluye diffs si es necesario. Puedes usar wikicódigo. La firma se añadirá de forma automática.',
        id: 'reasontextareanode'
    })

    form.append({
        type: 'submit',
        label: 'Aceptar'
    });

    let result = form.render();
    reports_Window.setContent(result);
    reports_Window.display();

    // Changes names of add/remove user buttons to Spanish
    function changeButtonNames() {
        let moreBox = document.querySelector('input[value="more"]')
        moreBox.value = "añadir"
        moreBox.style.marginTop = '0.3em' // To separate it slightly from the rest of the elements
        moreBox.addEventListener("click", () => {
            let removeBox = document.querySelector('input[value="remove"]')
            removeBox.value = "eliminar"
            removeBox.style.marginLeft = '0.3em' // Idem as four code lines above
        })
    }

    // Automatically adds the name of the reported user to the form
    function setReportedUserName() {
        document.querySelector('input[name="usernamefield"]').value = reportedUser
    }

    setReportedUserName();
    changeButtonNames();
}

function reports_submitMessage(e) {
    let form = e.target;
    let input = Morebits.quickForm.getInputData(form);
    if (!input.reason && !motiveOptionsDict[input.motive].optionalReason) {
        alert("No se ha establecido un motivo.");
    } else if (input.motive == 'Otro' && input.otherreason == '') {
        alert("No se ha establecido un título para la denuncia");
    } else if (input.usernamefield == '') {
        alert("No se ha establecido un usuario");
    } else {
        let statusWindow = new Morebits.simpleWindow(400, 350);
        createStatusWindow(statusWindow);
        new Morebits.status("Paso 1", `obteniendo datos del formulario...`, "info");
        let usernames = Array.from(document.querySelectorAll('input[name=usernamefield]')).map((o) => o.value)
        let articles = Array.from(document.querySelectorAll('input[name=articlefieldbox]')).map((o) => o.value)
        new Morebits.status("Paso 2", `creando denuncia en el tablón...`, "info");
        new mw.Api().edit(
            motiveOptionsDict[input.motive].link,
            reports_buildEditOnNoticeboard(input, usernames, articles)
        )
            .then(function () {
                return reports_postsMessage(input)
            })
            .then(function () {
                if (currentPageName.includes(`_discusión:${reportedUser}`)) {
                    new Morebits.status("✔️ Finalizado", "actualizando página...", "status");
                    setTimeout(() => {
                        location.reload();
                    }, 2500);
                } else {
                    new Morebits.status("✔️ Finalizado", "cerrando ventana...", "status");
                    setTimeout(() => {
                        statusWindow.close();
                        reports_Window.close();
                    }, 2500);
                }
            })
            .catch(function (error) {
                new Morebits.status("❌ Se ha producido un error", "Comprueba las ediciones realizadas", "error");
                console.log(`Error: ${error}`);
                setTimeout(() => {
                    statusWindow.close();
                    reports_Window.close();
                }, 4000);
            })

    }
}

function listWords(array, templateLetter) {
    let bulletedWords = ''
    for (let word of array) {
        bulletedWords += `* {{${templateLetter}|${word}}} \n`
    }
    return bulletedWords
}

function VECReportBuilder(usernames, input) {
    let finalText = ''
    for (let user of usernames) {
        let templateWord = mw.util.isIPAddress(user, true) ? 'VándaloIP' : 'Vándalo';
        finalText += `=== ${user} ===` + '\n' + '\n' +
            `* Posible vándalo: {{${templateWord}|${user}}}` + '\n' +
            `* Motivo del reporte: ${input.reason}` + '\n' +
            '* Usuario que reporta: ~~~~' + '\n' +
            '* Acción administrativa: (a rellenar por un bibliotecario)' + '\n'
    }
    return finalText
}

function reports_buildEditOnNoticeboard(input, usernames, articles) {
    if (input.motive == "Vandalismo en curso") {
        return (revision) => {
            return {
                text: revision.content + '\n' + '\n' + VECReportBuilder(usernames, input),
                summary: `Creando denuncia de usuario mediante [[WP:Twinkle Lite|Twinkle Lite]]`,
                minor: false
            }
        }
    } else {
        let title = input.motive == "Otro" ? input.otherreason : input.motive;
        let bulletedUserList = listWords(usernames, 'u')
        let bulletedArticleList = listWords(articles, 'a')
        let reasonTitle = input.motive == "Guerra de ediciones" ? `; Comentario` : `; Motivo`;
        let articleListIfEditWar = input.motive == "Guerra de ediciones" ? `\n; Artículos en los que se lleva a cabo \n${bulletedArticleList} \n` : '\n';
        return (revision) => {
            return {
                text: revision.content + '\n' + '\n' +
                    `== ${title} ==` + '\n' +
                    `; ${motiveOptionsDict[input.motive].usersSubtitle}` + '\n' +
                    `${bulletedUserList}` +
                    articleListIfEditWar +
                    (motiveOptionsDict[input.motive].optionalReason && !input.reason ? '' : `${reasonTitle}\n${input.reason}\n`) +
                    '; Usuario que lo solicita' + '\n' +
                    '* ~~~~' + '\n' +
                    '; Respuesta' + '\n' +
                    '(a rellenar por un bibliotecario)',
                summary: `Creando denuncia de usuario mediante [[WP:Twinkle Lite|Twinkle Lite]]`,
                minor: false
            }
        }
    }
}

// Builds a regex to be used in the createHash function using the title of the report
function buildRegex(reportTitle) {
    const regExpString = String.raw`==\s*${reportTitle}\s*==`;
    return new RegExp(regExpString, 'g');
}

// Creates the hash to be used in the link to the appropriate board on the notified user's talk page
// Does so by examining the content of the board and counting the amount of similar titles
// It then returns the appropriate hash number corresponding to the id of the report's title
function createHash(board, reportTitle) {
    return getContent(board).then((boardContent) => {
        const regex = buildRegex(reportTitle);
        const otherOccurrences = boardContent.match(regex);
        if (otherOccurrences && otherOccurrences.length > 1) {
            return `${reportTitle}_${otherOccurrences.length}`
        }
        return reportTitle
    })
}

function reports_postsMessage(input) {
    if (!input.notify) return;
    new Morebits.status("Paso 3", `avisando al usuario reportado...`, "info");
    return isPageMissing(`Usuario_discusión:${input.usernamefield}`)
        .then(async function (mustCreateNewTalkPage) {
            const title = input.motive == "Otro" ? input.otherreason : input.motive;
            const hash = await createHash(motiveOptionsDict[input.motive].link, title);
            const notificationString = `Hola. Te informo de que he creado una denuncia —por la razón mencionada en el título— que te concierne. Puedes consultarla en el tablón correspondiente a través de '''[[${motiveOptionsDict[input.motive].link}#${input.motive == "Vandalismo en curso" ? reportedUser : hash}|este enlace]]'''. Un [[WP:B|bibliotecario]] se encargará de analizar el caso y emitirá una resolución al respecto próximamente. Un saludo. ~~~~`;
            if (mustCreateNewTalkPage) {
                return new mw.Api().create(
                    `Usuario_discusión:${input.usernamefield}`,
                    { summary: `Aviso al usuario de su denuncia por [[${motiveOptionsDict[input.motive].link}|${title.toLowerCase()}]] mediante [[WP:Twinkle Lite|Twinkle Lite]]` },
                    `\n== ${title} ==\n` +
                    notificationString
                );
            } else {
                return new mw.Api().edit(
                    `Usuario_discusión:${input.usernamefield}`,
                    function (revision) {
                        return {
                            text: revision.content + `\n== ${title} ==\n` + notificationString,
                            summary: `Aviso al usuario de su denuncia por [[${motiveOptionsDict[input.motive].link}|${title.toLowerCase()}]] mediante [[WP:Twinkle Lite|Twinkle Lite]]`,
                            minor: false
                        }
                    }
                )
            }
        })
}


;// CONCATENATED MODULE: ./src/modules/tags.js
// ** Tags module **
// Allows users to add a tag in articles. The tag can be selected as part of a series of options of a checkbox list



let tags_Window;

// Dictionary that stores the templates, the description, as well as the parameter and the name of the warning template if any of them is applicable
// Template parameters are set in the subgroup, specifically in the 'name' key, their syntax is as follows:
// `_param-parent template name-parameter identifier`
// If the parameter doesn't have an identifier, then just type a «1»

const relevantPageName = cleansePageName(currentPageName);
const relevantPageNameNoUnderscores = relevantPageName.replaceAll('_', ' ');

const templateDict = {
	"artículo bueno": {
		description: "para etiquetar artículos que han obtenido la calificación de AB"
	},
	"autotrad": {
		warning: "aviso autotrad",
		description: "uso de automatismo en traducciones de nula calidad"
	},
	"bulo": {
		warning: "aviso destruir|2=bulo",
		description: "páginas falsas que constituyen bulos o hoax"
	},
	"categorizar": {
		warning: "aviso categorizar",
		description: "artículos sin categorías"
	},
	"CDI": {
		warning: "aviso conflicto de interés",
		description: "escrita bajo conflicto de interés"
	},
	"categorizar": {
		warning: "aviso categorizar",
		description: "artículos que no poseen categorías"
	},
	"contextualizar": {
		warning: "aviso contextualizar",
		description: "el tema o ámbito no está claramente redactado. Plantilla de 30 días."
	},
	"complejo": {
		description: "textos difíciles de entender"
	},
	"copyedit": {
		warning: "aviso copyedit",
		description: "necesita una revisión de ortografía y gramática"
	},
	"curiosidades": {
		description: "textos con sección de curiosidades"
	},
	"desactualizado": {
		description: "página con información obsoleta"
	},
	"en desarrollo": {
		description: "páginas en construcción o siendo editadas activamente",
		subgroup: [
			{
				type: 'input',
				name: '_param-en desarrollo-1',
				label: 'Nombre del editor',
				tooltip: 'Escribe el nombre del usuario que está desarrollando el artículo, no utilices ningún tipo de Wikicódigo'
			}
		]
	},
	"evento actual": {
		description: "artículos de actualidad cuya información es susceptible a cambiar"
	},
	"excesivamente detallado": {
		description: "demasiada información sobre temas triviales"
	},
	"experto": {
		description: "artículos muy técnicos con deficiencias de contenido solo corregibles por un experto"
	},
	"ficticio": {
		description: "sin enfoque desde un punto de vista real"
	},
	"formato de referencias": {
		warning: "aviso formato de referencias",
		description: "referencias incorrectas o mal construidas"
	},
	"fuente primaria": {
		warning: "aviso fuente primaria",
		description: "información no verificable. Plantilla de 30 días."
	},
	"fuentes no fiables": {
		description: "referencias que no siguen la política de fuentes fiables",
		warning: "aviso fuentes no fiables"
	},
	"fusionar": {
		description: "sugerir una fusión",
		subgroup: [
			{
				type: 'input',
				name: '_param-fusionar-1',
				label: 'Artículo objetivo',
				tooltip: 'Escribe el nombre del artículo con el que quieres fusionar esta página. No uses Wikicódigo.'
			}
		]
	},
	"globalizar": {
		warning: "aviso globalizar",
		description: "existe sesgo territorial",
		subgroup: [
			{
				type: 'input',
				name: '_param-globalizar-1',
				label: 'Cultura o territorio del sesgo'
			}
		]
	},
	"infraesbozo": {
		warning: "aviso infraesbozo",
		description: "contenido insuficiente como para constituir un esbozo de artículo o anexo válido. Plantilla de 30 días",
	},
	"largo": {
		description: "artículos excesivamente largos que deberían subdividirse en varios"
	},
	"mal traducido": {
		warning: "aviso mal traducido",
		description: "escasa calidad de una traducción de otro idioma"
	},
	"mejorar redacción": {
		description: "redacciones que no siguen el manual de estilo"
	},
	"no es un foro": {
		description: "páginas de discusión que han recibido grandes cantidades de conversación irrelevante",
		talkPage: true
	},
	"no neutralidad": {
		warning: "aviso no neutralidad",
		description: "artículos sesgados o claramente decantados en una dirección",
		subgroup: [
			{
				type: 'input',
				name: `_param-no neutralidad-motivo`,
				label: 'Razón del sesgo',
				tooltip: 'Describe brevemente la razón del sesgo. Es importante, también, desarrollarla más exhaustivamente en la PD',
				required: true
			}
		]
	},
	"plagio": {
		warning: "aviso destruir|2=plagio",
		description: "artículos copiados, que violan derechos de autor",
		subgroup: [
			{
				type: 'input',
				name: '_param-plagio-1',
				label: 'URL origen del plagio',
				tooltip: 'Copia y pega aquí la URL de la página externa en la que se halla el texto original',
				required: true
			}
		]
	},
	"polémico": {
		description: "temas susceptibles a guerras de edición o vandalismo",
		talkPage: true
	},
	"pr": {
		description: "para atribuir el artículo a un wikiproyecto",
		subgroup: [
			{
				type: 'input',
				name: '_param-pr-1',
				label: 'Nombre del wikiproyecto',
				tooltip: 'Escribe aquí el nombre del Wikiproyecto (esta plantilla se coloca en la PD automáticamente)',
				required: true
			}
		],
		talkPage: true
	},
	"promocional": {
		warning: "aviso promocional",
		description: "texto con marcado carácter publicitario, no neutral. Plantilla de 30 días",
		subgroup: [
			{
				type: 'input',
				name: '_param-promocional-motivo',
				label: 'Motivo (opcional)',
				tooltip: 'Rellena este campo para especificar el motivo por el que se ha colocado la plantilla',
				required: false
			}
		]
	},
	"publicidad": {
		description: "contenido comercial que defiende proselitismos o propaganda"
	},
	"pvfan": {
		warning: "aviso no neutralidad|2=PVfan",
		description: "escritos poco neutrales, con punto de vista fanático"
	},
	"referencias": {
		warning: "aviso referencias",
		description: "artículos sin una sola referencia"
	},
	"referencias adicionales": {
		warning: "aviso referencias",
		description: "artículos con falta de referencias"
	},
	"renombrar": {
		description: "Para proponer un renombrado de una página",
		subgroup: [
			{
				type: 'input',
				name: '_param-renombrar-1',
				label: 'Nuevo nombre sugerido',
				required: true
			}
		]
	},
	"revisar traducción": {
		description: "texto traducido legible pero necesita un repaso lingüístico"
	},
	"sin relevancia": {
		warning: "aviso sin relevancia",
		description: "artículos que no superan umbral de relevancia. Plantilla de 30 días",
		subgroup: [
			{
				type: 'input',
				name: '_param-sin relevancia-motivo',
				label: 'Motivo (opcional)',
				tooltip: 'Rellena este campo para especificar el motivo por el que se ha colocado la plantilla',
				required: false
			}
		]
	},
	"traducción": {
		description: "artículos que se están traduciendo desde otro idioma",
		subgroup: [
			{
				type: 'input',
				name: '_param-traducción-ci',
				label: 'Código ISO del idioma (opcional)',
				tooltip: 'Añade el código ISO del idioma del que procede la traducción. Ejemplo: «en» para artículos que proceden de la Wikipedia en inglés o «fr» si vienen de frwiki',
				required: false
			}
		]
	},
	"traducción incompleta": {
		warning: "aviso traducción incompleta",
		description: "artículos que han sido traducidos solo parcialmente"
	},
	"wikificar": {
		warning: "aviso wikificar",
		description: "textos con mal formato o que no cumplen el manual de estilo"
	}
}

// Builds the link to be displayed in each checkbox description
function linkBuilder(link) {
	let fullLink = `https://es.wikipedia.org/wiki/Plantilla:${link}`
	return `<a href="${fullLink}" target="_blank">(+)</a>`
}

// Builds the list to be passed as parameter to the Morebits function that creates the box holding all the options
// The data is gathered from the dictionary
function listBuilder(list) {
	let finalList = [];
	for (let item in list) {
		let template = {};
		template.name = item
		template.value = item
		template.label = `{{${item}}} · ${list[item].description} ${linkBuilder(item)}`
		template.subgroup = list[item]?.subgroup ? list[item].subgroup : '';
		finalList.push(template)
	}
	return finalList;
}

// Creates the Morebits window holding the form
function tags_createFormWindow() {
	tags_Window = new Morebits.simpleWindow(620, 530);
	tags_Window.setScriptName('Twinkle Lite');
	tags_Window.setTitle('Añadir plantilla');
	tags_Window.addFooterLink('Portal de mantenimiento', 'Portal:Mantenimiento');
	let form = new Morebits.quickForm(tags_submitMessage);

	form.append({
		type: 'input',
		value: '',
		name: 'search',
		label: 'Búsqueda:',
		id: 'search',
		size: '30',
		event: function quickFilter() {
			const searchInput = document.getElementById("search");
			const allCheckboxDivs = document.querySelectorAll("#checkboxContainer > div");
			if (this.value) {
				// Flushes the list before calling the search query function, then does it as a callback so that it happens in the right order
				function flushList(callback) {
					for (let i = 0; i < allCheckboxDivs.length; i++) {
						const div = allCheckboxDivs[i];
						div.style.display = 'none';
					}
					callback();
				}
				// Finds matches for the search query within the checkbox list
				function updateList(searchString) {
					for (let i = 0; i < allCheckboxDivs.length; i++) {
						let checkboxText = allCheckboxDivs[i].childNodes[1].innerText
						if (checkboxText.includes(searchString.toLowerCase()) || checkboxText.includes(searchString.toUpperCase())) {
							const div = allCheckboxDivs[i];
							div.style.display = '';
						}
					}
				}
				flushList(() => updateList(searchInput.value));
			}
			// Retrieves the full list if nothing is on the search input box
			if (this.value.length == 0) {
				for (let i = 0; i < allCheckboxDivs.length; i++) {
					const div = allCheckboxDivs[i];
					div.style.display = '';
				}
			}
		}
	})

	let optionBox = form.append({
		type: 'div',
		id: 'tagWorkArea',
		className: 'morebits-scrollbox',
		style: 'max-height: 28em; min-height: 0.5em;'
	})

	optionBox.append({
		type: 'checkbox',
		id: 'checkboxContainer',
		list: listBuilder(templateDict),
		label: 'checkOption'
	})

	let optionsField = form.append({
		type: 'field',
		label: 'Opciones:'
	})

	optionsField.append({
		type: 'checkbox',
		list:
			[{
				name: "notify",
				value: "notify",
				label: "Notificar al creador de la página si es posible",
				checked: false,
				tooltip: "Marca esta casilla para que Twinkle Lite deje un mensaje automático en la página de discusión del creador del artículo advertiéndole de la colocación de la plantilla"
			}],
	})

	optionsField.append({
		type: 'input',
		name: 'reason',
		label: 'Razón:',
		tooltip: '(Opcional) Escribe aquí el resumen de edición explicando la razón por la que se ha añadido la plantilla',
		style: 'width: 80%; margin-top: 0.5em;'
	})

	form.append({
		type: 'submit',
		label: 'Aceptar'
	});

	let result = form.render();
	tags_Window.setContent(result);
	tags_Window.display();
}

function tags_submitMessage(e) {
	let form = e.target;
	let input = Morebits.quickForm.getInputData(form);
	let templateList = [];
	let templateTalkPageList = [];

	// First let's tidy up Morebit's array
	for (const [key, value] of Object.entries(input)) {
		if (value && !key.includes('_param') && key != 'notify' && key != 'reason' && key != 'search') {
			if (templateDict[key]?.talkPage) {
				templateTalkPageList.push([key])
			} else {
				templateList.push([key])
			}
		}
	}

	if (templateList.length < 1 && templateTalkPageList.length < 1) {
		return alert('No se ha seleccionado ninguna plantilla');
	}

	let statusWindow = new Morebits.simpleWindow(400, 350);
	createStatusWindow(statusWindow);
	new Morebits.status("Paso 1", `generando plantilla(s)...`, "info");
	makeAllEdits(templateList, templateTalkPageList, input)
		.then(function () {
			if (!input.notify) return;
			return getCreator().then(tags_postsMessage(templateList));
		})
		.then(function () {
			new Morebits.status("✔️ Finalizado", "actualizando página...", "status");
			setTimeout(() => { location.reload() }, 2000);
		})
		.catch(function (error) {
			new Morebits.status("❌ Se ha producido un error", "Comprueba las ediciones realizadas", "error");
			console.log(`Error: ${error}`);
		})

}

async function makeEdit(templates, input, pagename) {
	return await new mw.Api().edit(
		pagename,
		function (revision) {
			return {
				text: templateBuilder(templates) + revision.content,
				summary: `Añadiendo plantilla mediante [[WP:TL|Twinkle Lite]]` + `${input.reason ? `. ${input.reason}` : ''}`,
				minor: false
			}
		}
	)
}

// This functions assigns each parameter to their corresponding value and makes it accessible
function paramAssigner(list, input) {
	for (const element of list) {
		for (const [key, value] of Object.entries(input)) {
			if (key.includes('_param') && key.includes(element)) {
				list[element] = {
					"param": key.split('-').pop(),
					"paramValue": value
				}
			}
		}
	}
	return list;
}

async function makeAllEdits(templateList, templateTalkPageList, input) {
	if (templateList.length > 0) {
		templateList = paramAssigner(templateList, input);
		await makeEdit(templateList, input, relevantPageName);
	}
	if (templateTalkPageList.length > 0) {
		const talkPage = currentNamespace >= 104 ? `Anexo_discusión:${relevantPageName.substring(6)}` : `Discusión:${relevantPageName}`;
		templateTalkPageList = paramAssigner(templateTalkPageList, input);
		return isPageMissing(talkPage)
			.then(function (mustCreateNewTalkPage) {
				if (mustCreateNewTalkPage) {
					return new mw.Api().create(
						talkPage,
						{ summary: `Añadiendo plantilla mediante [[WP:TL|Twinkle Lite]]` + `${input.reason ? `. ${input.reason}` : ''}` },
						templateBuilder(templateTalkPageList)
					);
				} else {
					return makeEdit(
						templateTalkPageList,
						input,
						talkPage
					);
				}
			})
	}
}

function templateBuilder(list) {
	let finalString = '';
	for (const element of list) {
		const noSust = templateDict[element]?.talkPage ? true : false; /* Check whether the template uses sust or not (TP templates don't) */
		let parameter = list[element]?.param ? `|${list[element].param}=` : '';
		let parameterValue = list[element]?.paramValue || '';
		finalString += `{{${noSust ? '' : 'sust:'}${element}${parameter}${parameterValue}}}\n`;
	}
	return finalString;
}

function allWarnings(list) {
	let finalString = ''
	for (let template of list) {
		if (templateDict[template]?.warning) {
			finalString += `{{sust:${templateDict[template].warning}|${relevantPageNameNoUnderscores}}} ~~~~\n`
		}
	}
	return finalString
}

function tags_postsMessage(templateList) {
	return (creator) => {
		if (creator == currentUser) {
			return;
		} else {
			new Morebits.status("Paso 2", "publicando un mensaje de aviso en la página de discusión del creador (si es posible)...", "info");
			return isPageMissing(`Usuario_discusión:${creator}`)
				.then(function (mustCreateNewTalkPage) {
					const templates = allWarnings(templateList);
					if (!templates) {
						return;
					}
					if (mustCreateNewTalkPage) {
						return new mw.Api().create(
							`Usuario_discusión:${creator}`,
							{ summary: `Aviso al usuario de la colocación de una plantilla en [[${relevantPageNameNoUnderscores}]] mediante [[WP:Twinkle Lite|Twinkle Lite]]` },
							`${templates}`
						);
					} else {
						return new mw.Api().edit(
							`Usuario_discusión:${creator}`,
							function (revision) {
								return {
									text: revision.content + `\n${templates}`,
									summary: `Aviso al usuario de la colocación de una plantilla en [[${relevantPageNameNoUnderscores}]] mediante [[WP:Twinkle Lite|Twinkle Lite]]`,
									minor: false
								}
							}
						)
					}
				})
		}
	}
}


;// CONCATENATED MODULE: ./src/modules/warnings.js
// ** Warn module **
// Posts a warning message on a user discussion page that can be selected as part of a series of options of a checkbox list



let warnedUser;
let warnings_Window;

const warnings_templateDict = {
    "aviso autopromoción": {
        description: "usuarios creadores de páginas promocionales o de publicidad",
        subgroup: [
            {
                type: 'input',
                name: '_param-aviso autopromoción-1',
                label: 'Artículo promocional en cuestión',
                tooltip: 'Escribe el nombre del artículo considerado promocional o publicitario. No uses corchetes, el enlace se añadirá automáticamente'
            }
        ]
    },
    "aviso blanqueo": {
        description: "usuarios que han blanqueado total o parcialmente páginas en general o de discusión asociada",
        subgroup: [
            {
                type: 'input',
                name: '_param-aviso blanqueo-1',
                label: 'Artículo en el que se realizó el blanqueo',
                tooltip: 'Escribe el nombre del artículo en el que se realizó el blanqueo parcial o total. No uses corchetes, el enlace se añadirá automáticamente'
            }
        ]
    },
    "aviso blanqueo discusión": {
        description: "usuarios que han blanqueado total o parcialmente su página de discusión o la de otros usuarios",
    },
    "aviso categorizar": {
        description: "usuarios que han olvidado categorizar artículos",
        subgroup: [
            {
                type: 'input',
                name: '_param-aviso categorizar-1',
                label: 'Artículo en cuestión',
                tooltip: 'Escribe el nombre del artículo que no ha sido categorizado por el usuario. No uses corchetes, el enlace se añadirá automáticamente'
            }
        ]
    },
    "aviso conflicto de interés": {
        description: "usuarios que editan bajo conflicto de interés o que constituyen CPP y no respetan PVN"
    },
    "aviso copyvio": {
        description: "usuarios que han creado artículos que vulneran derechos de autor",
        subgroup: [
            {
                type: 'input',
                name: '_param-aviso copyvio-1',
                label: 'Artículo en el que hay copyvio',
                tooltip: 'Escribe el nombre del artículo en el que se han vulnerado derechos de autor. No uses corchetes, el enlace se añadirá automáticamente'
            }
        ]
    },
    "aviso etiqueta": {
        description: "usuarios que han faltado a la etiqueta, realizando ediciones o creando comentarios o páginas que pueden resultar ofensivas",
        subgroup: [
            {
                type: 'input',
                name: '_param-aviso etiqueta-1',
                label: 'Nombre del artículo donde se ha producido la falta de etiqueta',
                tooltip: 'Escribe el nombre de la página donde se ha producido la falta de etiqueta. No uses corchetes, el enlace se añadirá automáticamente'
            }
        ]
    },
    "aviso firma": {
        description: "usuarios que han firmado artículos",
        subgroup: [
            {
                type: 'input',
                name: '_param-aviso firma-1',
                label: 'Nombre del artículo donde se ha firmado erróneamente',
                tooltip: 'Escribe el nombre del artículo donde se ha añadido una firma. No uses corchetes, el enlace se añadirá automáticamente'
            }
        ]
    },
    "aviso guerra de ediciones": {
        description: "usuario que puede desconocer R3R y se encuentre en guerra o conflicto de ediciones",
        subgroup: [
            {
                type: 'input',
                name: '_param-aviso guerra de ediciones-1',
                label: 'Nombre de la página en la que se ha dado la guerra de ediciones',
                tooltip: 'Escribe el nombre de la página en la que el usuario avisado ha participado en una guerra de ediciones. No uses corchetes, el enlace se añadirá automáticamente'
            }
        ]
    },
    "aviso imagen": {
        description: "autores que han subido imágenes que no deberían estar en Commons",
        subgroup: [
            {
                type: 'input',
                name: '_param-aviso imagen-1',
                label: 'Nombre del archivo en Commons',
                tooltip: 'Escribe el nombre del archivo en Commons, incluyendo su extensión. No uses corchetes, el enlace se añadirá automáticamente'
            }
        ]
    },
    "aviso noesunforo2": {
        description: "usuarios que forean en páginas de discusión",
        subgroup: [
            {
                type: 'input',
                name: '_param-aviso noesunforo2-1',
                label: 'Artículo en el que se realizó la edición',
                tooltip: 'Escribe el nombre del artículo en el que se cometió la prueba de edición. No uses corchetes, el enlace se añadirá automáticamente'
            }
        ]
    },
    "aviso nombre inapropiado": {
        description: "nombres de usuario que van contra la política de nombres de usuario"
    },
    "aviso prueba1": {
        description: "usuarios que han realizado ediciones no apropiadas",
        subgroup: [
            {
                type: 'input',
                name: '_param-aviso prueba1-1',
                label: 'Artículo en el que se realizó la edición',
                tooltip: 'Escribe el nombre del artículo en el que se cometió la prueba de edición. No uses corchetes, el enlace se añadirá automáticamente'
            }
        ]
    },
    "aviso prueba2": {
        description: "usuarios que han realizado ediciones vandálicas",
        subgroup: [
            {
                type: 'input',
                name: '_param-aviso prueba2-1',
                label: 'Artículo en el que se realizó el vandalismo',
                tooltip: 'Escribe el nombre del artículo en el que se cometió el vandalismo. No uses corchetes, el enlace se añadirá automáticamente'
            }
        ]
    },
    "aviso prueba3": {
        description: "usuarios que han realizado más de una edición vandálica",
        subgroup: [
            {
                type: 'input',
                name: '_param-aviso prueba3-1',
                label: 'Artículo en el que se llevó a cabo el vandalismo',
                tooltip: 'Escribe el nombre del artículo en elviso noesunforo1 que se cometió el vandalismo. No uses corchetes, el enlace se añadirá automáticamente'
            }
        ]
    },
    "aviso prueba4": {
        description: "ultimo aviso a usuarios vandálicos antes de denunciarlo en TAB",
        subgroup: [
            {
                type: 'input',
                name: '_param-aviso prueba4-1',
                label: 'Artículo en el que se llevó a cabo el vandalismo',
                tooltip: 'Escribe el nombre del artículo en el que se cometió el vandalismo. No uses corchetes, el enlace se añadirá automáticamente'
            }
        ]
    },
    "aviso sin sentido": {
        description: "usuarios que crean páginas sin sentido o bulos",
        subgroup: [
            {
                type: 'input',
                name: '_param-aviso sin sentido-1',
                label: 'Artículo en el que se llevó a cabo la edición',
                tooltip: 'Escribe el nombre del artículo en el que se llevó a cabo la edición sin sentido o bulo. No uses corchetes, el enlace se añadirá automáticamente',
                required: true
            }
        ]
    },
    "aviso topónimos de España": {
        description: "usuarios que no han tenido en cuenta WP:TOES",
        subgroup: [
            {
                type: 'input',
                name: '_param-aviso topónimos de España-1',
                label: 'Artículo en cuestión',
                tooltip: 'Escribe el nombre de la página en la que se ha violado la política de WP:TOES. No uses corchetes, el enlace se añadirá automáticamente',
            }
        ]
    },
    "aviso tradref": {
        description: "usuarios que han traducido un artículo pero no han agregado la atribución o referencias a copyright correspondientes",
        subgroup: [
            {
                type: 'input',
                name: '_param-aviso tradref-1',
                label: 'Nombre del artículo',
                tooltip: 'Escribe el nombre del artículo en el que no se ha añadido la atribución correcta, sin usar corchetes',
            }
        ]
    },
    "aviso traslado al taller": {
        description: "usuarios que han creado una página no apta para el espacio principal",
        subgroup: [
            {
                type: 'input',
                name: '_param-aviso traslado al taller-1',
                label: 'Página (del taller) en la que se encuentra el artículo trasladado',
                tooltip: 'Escribe el nombre de la página en la que se encuentra ahora el artículo (Ej.: si pones «EjemploDePágina», el enlace llevará a «Usuario:Ejemplo/Taller/EjemploDePágina»). No uses corchetes, el enlace se añadirá automáticamente',
            }
        ]
    },
    "aviso votonulo": {
        description: "usuarios que han intentado votar sin cumplir los requisitos"
    },
    "no amenaces con acciones legales": {
        description: "usuarios que han amenazado con denunciar o llevar a juicio a Wikipedia/otros usuarios",
        subgroup: [
            {
                type: 'input',
                name: '_param-no amenaces con acciones legales-1',
                label: 'Página en la que se llevó a cabo la amenaza',
                tooltip: '(Opcional) Escribe el nombre de la página en la que se llevó a cabo la amenaza. No uses corchetes, el enlace se añadirá automáticamente'
            }
        ]
    },
    "no retires plantillas de mantenimiento crítico": {
        description: "usuarios que han retirado plantillas de mantenimiento crítico sin consenso en PD",
        subgroup: [
            {
                type: 'input',
                name: '_param-no retires plantillas de mantenimiento crítico-1',
                label: 'Artículo en el que se retiró la plantilla',
                tooltip: 'Escribe el nombre del artículo en el que se encontraba la plantilla retirada. No uses corchetes, el enlace se añadirá automáticamente'
            }
        ]
    },
    "planvand": {
        description: "usuarios que han realizado ediciones perjudiciales o que van más allá del vandalismo",
        subgroup: [
            {
                type: 'input',
                name: '_param-planvand-1',
                label: 'Artículo en el que se llevó a cabo el vandalismo',
                tooltip: 'Escribe el nombre del artículo en el que se cometió el vandalismo. No uses corchetes, el enlace se añadirá automáticamente'
            }
        ]
    },
    "ten precaución en la retirada de plantillas de mantenimiento no crítico": {
        description: "usuarios que han retirado plantillas de mantenimiento no crítico sin explicaciones",
        subgroup: [
            {
                type: 'input',
                name: '_param-ten precaución en la retirada de plantillas de mantenimiento no crítico-1',
                label: 'Artículo del que se retiró la plantilla',
                tooltip: 'Escribe el nombre del artículo en el que se produjo la retirada indebida de la plantilla de mantenimiento no crítico. No uses corchetes, el enlace se añadirá automáticamente'
            }
        ]
    }

}

function warnings_linkBuilder(link) {
    let fullLink = `https://es.wikipedia.org/wiki/Plantilla:${link}`
    return `<a href="${fullLink}" target="_blank">(+)</a>`
}

function warnings_listBuilder(list) {
    let finalList = [];
    for (let item in list) {
        let template = {};
        template.name = item
        template.value = item
        template.label = `{{${item}}} · ${list[item].description} ${warnings_linkBuilder(item)}`
        template.subgroup = list[item]?.subgroup ? list[item].subgroup : '';
        finalList.push(template)
    }
    return finalList;
}

function warnings_templateBuilder(list) {
    let finalString = '';
    for (const element of list) {
        let parameter = list[element]?.param ? `|${list[element].param}=` : '';
        let parameterValue = list[element]?.paramValue || '';
        finalString += `{{sust:${element}${parameter}${parameterValue}}}\n`;
    }
    return finalString;
}

// Creates the Morebits window holding the form
function warnings_createFormWindow(warnedUserFromDOM) {

    // Something about the addPortletLink feature doesn't work well so this condition is unfortunately needed
    if (typeof warnedUserFromDOM == 'string') {
        warnedUser = warnedUserFromDOM;
    } else {
        warnedUser = relevantUserName;
    }

    warnings_Window = new Morebits.simpleWindow(620, 530);
    warnings_Window.setScriptName('Twinkle Lite');
    warnings_Window.setTitle('Avisar al usuario');
    warnings_Window.addFooterLink('Plantillas de aviso a usuario', 'Wikipedia:Plantillas de aviso a usuario');
    let form = new Morebits.quickForm(warnings_submitMessage);

    form.append({
        type: 'input',
        value: '',
        name: 'search',
        label: 'Búsqueda:',
        id: 'search',
        size: '30',
        event: function quickFilter() {
            const searchInput = document.getElementById("search");
            const allCheckboxDivs = document.querySelectorAll("#checkboxContainer > div");
            if (this.value) {
                // Flushes the list before calling the search query function, then does it as a callback so that it happens in the right order
                function flushList(callback) {
                    for (let i = 0; i < allCheckboxDivs.length; i++) {
                        const div = allCheckboxDivs[i];
                        div.style.display = 'none';
                    }
                    callback();
                }
                // Finds matches for the search query within the checkbox list
                function updateList(searchString) {
                    for (let i = 0; i < allCheckboxDivs.length; i++) {
                        let checkboxText = allCheckboxDivs[i].childNodes[1].innerText
                        if (checkboxText.includes(searchString.toLowerCase()) || checkboxText.includes(searchString.toUpperCase())) {
                            const div = allCheckboxDivs[i];
                            div.style.display = '';
                        }
                    }
                }
                flushList(() => updateList(searchInput.value));
            }
            // Retrieves the full list if nothing is on the search input box
            if (this.value.length == 0) {
                for (let i = 0; i < allCheckboxDivs.length; i++) {
                    const div = allCheckboxDivs[i];
                    div.style.display = '';
                }
            }
        }
    })

    let optionBox = form.append({
        type: 'div',
        id: 'tagWorkArea',
        className: 'morebits-scrollbox',
        style: 'max-height: 28em; min-height: 0.5em;'
    })

    optionBox.append({
        type: 'checkbox',
        id: 'checkboxContainer',
        list: warnings_listBuilder(warnings_templateDict)
    })

    let optionsField = form.append({
        type: 'field',
        label: 'Opciones:'
    })

    optionsField.append({
        type: 'input',
        name: 'reason',
        label: 'Razón:',
        tooltip: '(Opcional) Escribe aquí el resumen de edición explicando la razón por la que se ha añadido la plantilla',
        style: 'width: 80%; margin-top: 0.5em;'
    })

    form.append({
        type: 'submit',
        label: 'Aceptar'
    });

    let result = form.render();
    warnings_Window.setContent(result);
    warnings_Window.display();

}

function warnings_submitMessage(e) {
    let form = e.target;
    let input = Morebits.quickForm.getInputData(form);
    let templateList = [];

    // First let's tidy up Morebit's array
    for (const [key, value] of Object.entries(input)) {
        if (value && !key.includes('_param') && key != 'notify' && key != 'reason' && key != 'search') {
            templateList.push([key])
        }
    }

    // Then we will assign each parameter to their corresponding value and make it accessible
    for (const element of templateList) {
        for (const [key, value] of Object.entries(input)) {
            if (key.includes('_param') && key.includes(element)) {
                templateList[element] = {
                    "param": key.split('-').pop(),
                    "paramValue": value
                }
            }
        }
    }


    if (warnedUser == currentUser) {
        alert("No puedes dejarte un aviso a ti mismo");
        return;
    } else {
        let statusWindow = new Morebits.simpleWindow(400, 350);
        createStatusWindow(statusWindow);
        new Morebits.status("Paso 1", 'generando plantilla...', 'info');
        warnings_postsMessage(templateList, input)
            .then(function () {
                if (currentPageName.includes(`_discusión:${warnedUser}`)) {
                    new Morebits.status("✔️ Finalizado", "actualizando página...", "status");
                    setTimeout(() => {
                        location.reload();
                    }, 2000);
                } else {
                    new Morebits.status("✔️ Finalizado", "cerrando ventana...", "status");
                    setTimeout(() => {
                        statusWindow.close();
                        warnings_Window.close();
                    }, 2500);
                }
            })
            .catch(function (error) {
                new Morebits.status("❌ Se ha producido un error", "Comprueba las ediciones realizadas", "error");
                console.log(`Error: ${error}`);
                setTimeout(() => {
                    statusWindow.close();
                    warnings_Window.close();
                }, 4000);
            })
    }

}

function warnings_postsMessage(templateList, input) {
    new Morebits.status("Paso 2", "publicando aviso en la página de discusión del usuario", "info");
    return isPageMissing(`Usuario_discusión:${warnedUser}`)
        .then(function (mustCreateNewTalkPage) {
            if (mustCreateNewTalkPage) {
                return new mw.Api().create(
                    `Usuario_discusión:${warnedUser}`,
                    { summary: `Añadiendo aviso de usuario mediante [[WP:Twinkle Lite|Twinkle Lite]]` + `${input.reason ? `. ${input.reason}` : ''}` },
                    `${warnings_templateBuilder(templateList)}~~~~`
                );
            } else {
                return new mw.Api().edit(
                    `Usuario_discusión:${warnedUser}`,
                    function (revision) {
                        return {
                            text: revision.content + `\n${warnings_templateBuilder(templateList)}~~~~`,
                            summary: `Añadiendo aviso de usuario mediante [[WP:Twinkle Lite|Twinkle Lite]]` + `${input.reason ? `. ${input.reason}` : ''}`,
                            minor: false
                        }
                    }
                )
            }
        })
}



;// CONCATENATED MODULE: ./src/modules/hide.js
let diffID;

function hide_createFormWindow(diff) {
    diffID = diff;

    Window = new Morebits.simpleWindow(620, 530);
    Window.setScriptName('Twinkle Lite');
    Window.setTitle('Solicitar ocultado de edición');
    Window.addFooterLink('Política de supresores', 'Wikipedia:Supresores');

    let form = new Morebits.quickForm(hide_submitMessage);

    form.append({
        type: 'textarea',
        name: 'reason',
        label: 'Describe el motivo (opcional):',
        tooltip: 'Puedes usar wikicódigo en tu descripción, tu firma se añadirá automáticamente.'
    });

    let optionsField = form.append({
        type: 'field',
        label: 'Opciones:',
    })


    optionsField.append({
        type: 'checkbox',
        list:
            [{
                name: "otherArticles",
                value: "otherArticles",
                label: 'Incluir más diffs en la solicitud',
                checked: false,
            }],
        name: 'moreDiffsCheckbox',
        event: (e) => {
            const checked = e.target.checked;
            const inputField = document.getElementById('moreDiffsInputField');
            if (checked) {
                inputField.style.display = '';
            } else {
                inputField.style.display = 'none';
            }
            updateLabel(checked);
        }
    })

    optionsField.append({
        type: 'input',
        label: 'Escribe el ID de otros diffs que quieras incluir, separados por comas:<br> <i>Ejemplo: «159710180, 159635315»</i><br>',
        tooltip: 'El ID es el número de nueve cifras que aparece al final de la URL en una página de diff después de «oldid=»',
        style: "display: none;",
        id: 'moreDiffsInputField',
    })

    form.append({
        type: 'submit',
        label: 'Aceptar'
    });


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

    updateLabel();

}

function updateLabel(checkstatus = false) {
    const label = document.querySelector('label[for=moreDiffsInputField]');
    if (checkstatus) {
        label.style.display = '';
    } else {
        label.style.display = 'none';
    }
}

function hide_submitMessage(e) {
    let form = e.target;
    let input = Morebits.quickForm.getInputData(form);
    console.log(input);
}


;// CONCATENATED MODULE: ./src/index.js









if (!window.TwinkleLite) {

	window.TwinkleLite = true;

	function createHideButton() {
		const parentElement = document.querySelector('.mw-diff-undo').parentElement;
		if (parentElement) {
			const hideButton = document.createElement('span');
			const tooltip = "Solicita que esta edición sea ocultada en el TAB";
			hideButton.innerHTML = ` (<a class="TL-hide-button" title="${tooltip}">ocultar</a>)`;
			parentElement.appendChild(hideButton);
			const hideLink = document.querySelector('.TL-hide-button');
			hideLink.addEventListener('click', () => {
				hide_createFormWindow(diffNewId);
			});
		};
	}

	function createReportButton() {
		const usersNodeList = document.querySelectorAll('a.mw-usertoollinks-talk');
		usersNodeList.forEach(
			(element) => {
				if (element.parentElement.querySelector('a.extiw')) {
					return;
				}
				const newElement = document.createElement('span');
				newElement.textContent = ' · ';
				const elementChild = document.createElement('a')
				elementChild.id = 'report-button';
				elementChild.textContent = 'denunciar';
				elementChild.style.color = '#924141';
				elementChild.addEventListener('click', () => {
					let username;
					// This looks cumbersome but it's the only way to get the right username across both skins and instances
					if (currentPageName == "Especial:PáginasNuevas") {
						username = element.parentElement.parentElement.querySelector('bdi').innerText;
					} else {
						username = element.parentElement.parentElement.parentElement.querySelector('bdi').innerText;
					}
					reports_createFormWindow(username);
				})
				newElement.append(elementChild);
				element.parentNode.insertBefore(newElement, element.nextSibling);
			}
		)
	}

	function createWarningButton() {
		const usersNodeList = document.querySelectorAll('a.mw-usertoollinks-talk');
		usersNodeList.forEach(
			(element) => {
				if (element.parentElement.querySelector('a.extiw')) {
					return;
				}
				const newElement = document.createElement('span');
				newElement.textContent = ' · ';
				const elementChild = document.createElement('a');
				elementChild.id = 'warning-button';
				elementChild.textContent = 'aviso';
				elementChild.style.color = 'teal';
				elementChild.addEventListener('click', () => {
					// This looks cumbersome but it's the only way to get the right username across all skins and instances
					let username = element.parentElement.parentElement.parentElement.querySelector('bdi').innerText;
					warnings_createFormWindow(username);
				})
				newElement.append(elementChild);
				element.parentNode.insertBefore(newElement, element.nextSibling);
			})
	}

	const loadDependencies = (callback) => {
		mw.loader.using(['mediawiki.user', 'mediawiki.util', 'mediawiki.Title', 'jquery.ui', 'mediawiki.api', 'mediawiki.ForeignApi']);
		callback();
	}

	const loadMorebits = (callback) => {
		mw.loader.load('https://en.wikipedia.org/w/index.php?title=MediaWiki:Gadget-morebits.js&action=raw&ctype=text/javascript', 'text/javascript');
		mw.loader.load('https://en.wikipedia.org/w/index.php?title=MediaWiki:Gadget-morebits.css&action=raw&ctype=text/css', 'text/css');
		callback();
	};

	const initializeTwinkleLite = () => {
		console.log("Loading Twinkle Lite...");

		if (currentNamespace < 0 || !mw.config.get('wgArticleId')) {
			console.log("Special or non-existent page: PP will therefore not be loaded.");
			console.log("Special or non-existent page: DRM will therefore not be loaded.");
			console.log("Special or non-existent page: Speedy deletion will therefore not be loaded.");
		} else {
			const DRMportletLink = mw.util.addPortletLink('p-cactions', '#', 'Abrir CDB', 'TL-button', 'Abre una consulta de borrado para esta página');
			if (DRMportletLink) {
				DRMportletLink.onclick = createFormWindow;
			}
			const SDportletLink = mw.util.addPortletLink('p-cactions', '#', 'Borrado rápido', 'TL-button', 'Solicita el borrado rápido de la página');
			if (SDportletLink) {
				SDportletLink.onclick = speedydeletion_createFormWindow;
			}
		}

		if (currentNamespace >= 0) {
			const PPportletLink = mw.util.addPortletLink('p-cactions', '#', 'Pedir protección', 'TL-button', 'Solicita que esta página sea protegida');
			if (PPportletLink) {
				PPportletLink.onclick = pageprotection_createFormWindow;
			}
		}

		if (currentNamespace === 0 || currentNamespace === 1 || currentNamespace === 104 || currentNamespace === 105) {
			const TportleltLink = mw.util.addPortletLink('p-cactions', '#', 'Añadir plantilla', 'TL-button', 'Añade una plantilla a la página');
			if (TportleltLink) {
				TportleltLink.onclick = tags_createFormWindow;
			}
		}

		if (currentNamespace === 2 || currentNamespace === 3 || (mw.config.get('wgPageName').indexOf("Especial:Contribuciones") > -1)) {
			const RportletLink = mw.util.addPortletLink('p-cactions', '#', 'Denunciar usuario', 'TL-button', 'Informa de un problema en relación con el usuario');
			if (RportletLink) {
				RportletLink.onclick = reports_createFormWindow;
			}
			const WportletLink = mw.util.addPortletLink('p-cactions', '#', 'Avisar al usuario', 'TL-button', 'Deja una plantilla de aviso al usuario en su página de discusión');
			if (WportletLink) {
				WportletLink.onclick = warnings_createFormWindow;
			}
		}

		if (
			currentAction == 'history' ||
			currentPageName == "Especial:Seguimiento" ||
			currentPageName == "Especial:CambiosRecientes" ||
			currentPageName == "Especial:PáginasNuevas" ||
			diffNewId !== null
		) {
			mw.hook('wikipage.content').add(() => {
				if (document.querySelectorAll('a.mw-userlink').length > 0 && !document.getElementById('report-button')) {
					createWarningButton();
					createReportButton();
				}
			})
		}

		if (diffNewId) {
			mw.hook('wikipage.content').add(() => {
				createHideButton();
			})
		}

	};

	const loadTwinkleLite = () => {
		loadDependencies(() => {
			loadMorebits(() => {
				initializeTwinkleLite();
			});
		})
	};

	loadTwinkleLite();
} else {
	console.log('Parece que Twinkle Lite se ha intentado cargar dos veces. Comprueba la configuración para evitar la doble importación del script.');
}


/******/ })()
;
//</nowiki>