Usuario:Nacaru/DeletionRequestMaker.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 currentNamespace = mw.config.get('wgNamespaceNumber');

//Creates the window that holds the status messages
function createStatusWindow() {
    let Window = new Morebits.simpleWindow(400, 350);
    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: 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);
    let protectionPromise = apiPromise.then((data) => {
        let pages = data.query.pages;
        for (let p in pages) {
            let protectionLevel = pages[p].protection[0]?.level
            switch (protectionLevel) {
                case 'sysop':
                    return 'solo bibliotecarios';
                case 'autoconfirmed':
                    return 'solo usuarios autoconfirmados';
                case 'templateeditor':
                    return 'solo editores de plantillas'
                default:
                    return 'sin protección';
            }
        }
    });

    return protectionPromise;
}

// 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

}
;// CONCATENATED MODULE: ./src/modules/deletionrequestmaker.js


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' }
];

//Returns a boolean that states whether a spot for the creation of the DR page is available
// function canCreateDeletionRequestPage() {
//     return utils.isPageMissing(`Wikipedia:Consultas_de_borrado/${utils.currentPageName}`)
// }

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() {
    let Window = new Morebits.simpleWindow(620, 530);
    Window.setScriptName('Twinkle Lite');
    Window.setTitle('Consulta de borrado');
    Window.addFooterLink('Política de borrado', 'Wikipedia:Política de borrado');
    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; padding-bottom:0.5em;"
    })

    let result = form.render();
    Window.setContent(result);
    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?`)) {
            // canCreateDeletionRequestPage()
            //     .then(function (canMakeNewDeletionRequest) {
            //         if (!canMakeNewDeletionRequest) {
            //             throw new Error('La página no puede crearse. Ya existe una candidatura en curso o esta se cerró en el pasado.')
            // } else {
            createStatusWindow()
            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 página nominada...", "info");
                    return new mw.Api().edit(
                        currentPageName,
                        buildEditOnNominatedPage
                    )
                })
                .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 () {
                    new Morebits.status("Se ha producido un error", "Comprueba las ediciones realizadas", "error")
                    setTimeout(() => { location.reload() }, 4000);
                })
        }
    }
}

// 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) {
    console.log('debugging')
    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
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 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 pageprotection_createFormWindow() {
	let Window = new Morebits.simpleWindow(620, 530);
	Window.setScriptName('Twinkle Lite');
	Window.setTitle('Solicitar protección de la página');
	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: '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();
	Window.setContent(result);
	Window.display();

	getProtectionStatus(currentPageName).then(function (protectionLevel) {
		// Displays protection level on page
		let showProtection = document.querySelector("div[name='currentProtection'] > span.quickformDescription");
		showProtection.innerHTML = `Nivel actual de protección:<span style="color:royalblue; font-weight: bold;"> ${protectionLevel} <span>`
		// Disables "unprotect" option if not applicable
		if (protectionLevel == '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.reason === ``) {
		alert("No se ha establecido un motivo.");
	} else {
		if (window.confirm(`¿Quieres solicitar la ${input.protection} del artículo ${currentPageNameWithoutUnderscores}?`)) {
			createStatusWindow();
			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", "actualizando página...", "status");
					setTimeout(() => { location.reload() }, 1500);
				})
				.catch(function () {
					new Morebits.status("Se ha producido un error", "Comprueba las ediciones realizadas", "error")
					setTimeout(() => { location.reload() }, 4000);
				})
		}

	}
}

function buildEditOnNoticeboard(input) {
	let title = `== Solicitud de ${input.protection} de [[${currentPageNameWithoutUnderscores}]] ==`;
	if (input.protection === 'protección') {
		if (input.motive !== 'Otro') {
			title = `== Solicitud de ${input.protection} de [[${currentPageNameWithoutUnderscores}]] por ${input.motive.toLowerCase()} ==`;
		}
	};
	return (revision) => {
		return {
			text: revision.content + `\n
${title} 
;Artículo(s) 
* {{a|${currentPageNameWithoutUnderscores}}}
;Causa 
${input.reason}
; 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 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;
}

function speedydeletion_createFormWindow() {
    let Window = new Morebits.simpleWindow(620, 530);
    Window.setScriptName('Twinkle Lite');
    Window.setTitle('Solicitar borrado rápido');
    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();
    Window.setContent(result);
    Window.display();
}

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) {
        input.article.shift()
    }
    if (window.confirm(`¿Quieres solicitar el borrado del artículo ${currentPageNameWithoutUnderscores}?`)) {
        createStatusWindow();
        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 () {
                new Morebits.status("Se ha producido un error", "Comprueba las ediciones realizadas", "error")
                setTimeout(() => { location.reload() }, 4000);
            })
    }
}

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 = mw.config.get("wgRelevantUserName")

let reports_listMotiveOptions = [
    { value: "Cuenta creada para vandalizar" },
    { value: "CPP" },
    { 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 = {
    "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'
    },
    "CPP":
    {
        "link": "Wikipedia:Tablón_de_anuncios_de_los_bibliotecarios/Portal/Archivo/Nombres_inapropiados_y_vandalismo_persistente/Actual",
        "usersSubtitle": 'Lista de usuarios'
    },
    "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'
    },
    "Guerra de ediciones":
    {
        "link": "Wikipedia:Tablón_de_anuncios_de_los_bibliotecarios/Portal/Archivo/3RR/Actual",
        "usersSubtitle": 'Usuarios implicados'
    },
    "Nombre inapropiado":
    {
        "link": "Wikipedia:Tablón_de_anuncios_de_los_bibliotecarios/Portal/Archivo/Nombres_inapropiados_y_vandalismo_persistente/Actual",
        "usersSubtitle": 'Lista de usuarios'
    },
    "Violación de etiqueta":
    {
        "link": "Wikipedia:Tablón_de_anuncios_de_los_bibliotecarios/Portal/Archivo/Violaciones_de_etiqueta/Actual",
        "usersSubtitle": 'Usuarios implicados'
    },
    "Vandalismo en curso":
        { "link": "Wikipedia:Vandalismo_en_curso" },
    "Vandalismo persistente":
    {
        "link": "Wikipedia:Tablón_de_anuncios_de_los_bibliotecarios/Portal/Archivo/Nombres_inapropiados_y_vandalismo_persistente/Actual",
        "usersSubtitle": 'Lista de usuarios'
    },
    "Otro":
    {
        "link": "Wikipedia:Tablón_de_anuncios_de_los_bibliotecarios/Portal/Archivo/Miscelánea/Actual",
        "usersSubtitle": 'Usuarios implicados'
    }
}

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() {
    let Window = new Morebits.simpleWindow(620, 530);
    Window.setScriptName('Twinkle Lite');
    Window.setTitle('Denunciar usuario');
    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:'
                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')
                        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();
    Window.setContent(result);
    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
    document.querySelector('input[name="usernamefield"]').value = reportedUser
    changeButtonNames()
}

function reports_submitMessage(e) {
    let form = e.target;
    let input = Morebits.quickForm.getInputData(form);
    if (input.reason === `` && input.motive != 'NI') {
        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 {
        createStatusWindow()
        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 () {
                new Morebits.status("Finalizado", "actualizando página...", "status");
                setTimeout(() => { location.reload() }, 1500);
            })
            .catch(function () {
                new Morebits.status("Se ha producido un error", "Comprueba las ediciones realizadas", "error")
                setTimeout(() => { location.reload() }, 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 +
                    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
            }
        }
    }
}

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(function (mustCreateNewTalkPage) {
            let title = input.motive == "Otro" ? input.otherreason : input.motive;
            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` +
                    `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}#${title}|este enlace]]'''. Un [[WP:B|bibliotecario]] se encargará de analizar el caso y emitirá una resolución al respecto próximamente. Un saludo. ~~~~`
                );
            } else {
                return new mw.Api().edit(
                    `Usuario_discusión:${input.usernamefield}`,
                    function (revision) {
                        return {
                            text: revision.content + `\n== ${title} ==\n` + `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 : title}|este enlace]]'''. Un [[WP:B|bibliotecario]] se encargará de analizar el caso y emitirá una resolución al respecto próximamente. Un saludo. ~~~~`,
                            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



// 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 templateDict = {
	"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"
	},
	"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 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"
	},
	// "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
	// 		}
	// 	]
	// },
	"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 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() {
	let Window = new Morebits.simpleWindow(620, 530);
	Window.setScriptName('Twinkle Lite');
	Window.setTitle('Añadir plantilla');
	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();
	Window.setContent(result);
	Window.display();
}

function tags_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
				}
			}
		}
	}

	createStatusWindow();
	new Morebits.status("Paso 1", `generando plantilla...`, "info");
	new mw.Api().edit(
		currentPageName,
		function (revision) {
			return {
				text: templateBuilder(templateList) + revision.content,
				summary: `Añadiendo plantilla mediante [[WP:TL|Twinkle Lite]]` + `${input.reason ? `. ${input.reason}` : ''}`,
				minor: false
			}
		})
		.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 () {
			new Morebits.status("Se ha producido un error", "Comprueba las ediciones realizadas", "error")
			setTimeout(() => { location.reload() }, 4000);
		})



}

function 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;
}

function allWarnings(list) {
	let finalString = ''
	for (let template of list) {
		if (templateDict[template]?.warning) {
			finalString += `{{sust:${templateDict[template].warning}|${currentPageNameWithoutUnderscores}}} ~~~~\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 [[${currentPageNameWithoutUnderscores}]] 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 [[${currentPageNameWithoutUnderscores}]] 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



const warnedUser = mw.config.get('wgRelevantUserName');

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: "autores que han subido imágenes que no deberían estar en Commons",
        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 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() {
    let Window = new Morebits.simpleWindow(620, 530);
    Window.setScriptName('Twinkle Lite');
    Window.setTitle('Avisar al usuario');
    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();
    Window.setContent(result);
    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 {
        createStatusWindow();
        new Morebits.status("Paso 1", 'generando plantilla...', 'info');
        warnings_postsMessage(templateList, input)
            .then(function () {
                new Morebits.status("Finalizado", "actualizando página...", "status");
                setTimeout(() => { location.reload() }, 2000);
            })
            .catch(function () {
                new Morebits.status("Se ha producido un error", "Comprueba las ediciones realizadas", "error")
                setTimeout(() => { location.reload() }, 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/index.js








if (!window.TwinkleLite) {

	window.TwinkleLite = true;

	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 PPportletLink = mw.util.addPortletLink('p-cactions', '#', 'Pedir protección', 'TL-button', 'Solicita que esta página sea protegida');
			if (PPportletLink) {
				PPportletLink.onclick = pageprotection_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 || currentNamespace === 104) {
			const TportleltLink = mw.util.addPortletLink('p-cactions', '#', 'Añadir plantilla', 'TL-button', 'Añade una plantilla a la página');
			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');
			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');
			WportletLink.onclick = warnings_createFormWindow;
		} else {
			console.log("Non-user page: Reports will therefore not be loaded.");
		}
	};

	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>