Usuario:Nacaru/DeletionRequestMaker.js
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>