29-08-2023
/*
CC-BY-SA 4.0 higimo // v5.0.4
Вынесение на КБУ (+ отсроченное), КУ (+ множественное, + оставлено), КУЛ, КПМ.
Подключение (на своём /common.js):
var g_user_alert = 0 // указать, чтоб не уведомлять пользователя
importScript('u:higimo/remove.js');
*/
$(document).ready(function() {
/*
Инициализация итератора
*/
var i = 0,
/*
Инициализация переменной устанавливающей флаг на чекбоксе,
который влияет на выполнение функции оповещающей создателя статьи
*/
setAlert = (typeof g_user_alert == 'undefined') ? 1 : g_user_alert
/*
Список всех доступных причин КБУ
Коды для админов, текст для остальных.
Используется максимально короткий шаблон.
Третий параметр — условие для появления <input>
*/
fastRemove = [
['подст:ds', 'Медленное' ],
['уд-бессвязно', 'О1 Бессвязная статья' ],
['уд-тест', 'О2 Тестовая статья' ],
['уд-ванд', 'О3 Вандальная статья' ],
['уд-повторно', 'О4 Повторное создание' ],
['уд-автор', 'О5 Автор запросил удаление' ],
['уд-обс', 'О6 СО или подстраница' ],
['уд-переим', 'О7 Для переименования', 'страницу'],
['уд-дубль', 'О8 Дубликат статьи', 'страницу'],
['уд-реклама', 'О9 Реклама или спам' ],
['db-badtalk', 'О10 Нецелев. использ. СО' ],
['уд-копивио', 'О11 АП нарушены', 'ссылку'],
['уд-пусто', 'С1 Пусто или коротко' ],
['уд-иностр', 'С2 Надмозг' ],
['уд-ссылки', 'С3 Лишь ссылки' ],
['уд-нз', 'С5 Значимости нет' ],
['уд-в никуда', 'П1 Перенаправл. в никуда' ],
['db-redirspace', 'П2 Межпростр. перенаправ.' ],
['уд-опечатка', 'П3 Ошибочное перенап.' ],
['уд-падеж', 'П4 Не прав. падеж' ],
['уд-смысл', 'П5 Бессмысленное перенаправ.' ],
['db-redirtalk', 'П6 Перенаправление на СО' ],
['db-duplicate', 'Ф1 Копия файла', 'файл'],
['db-badimage', 'Ф2 Повреждённый файл' ],
['подст:nld', 'Ф3 Нет данных о лицензии' ],
['подст:nsd', 'Ф3 Нет данных о источнике' ],
['подст:nad', 'Ф3 Нет данных о авторе' ],
['подст:dd', 'Ф3 Сомнительные данные файла' ],
['подст:ofud', 'Ф4 Неиспользуемый КДИ' ],
['подст:dfud', 'Ф5 Нет КДИ' ],
['db-badfairuse', 'Ф6 Неоправданное КДИ' ],
['NCT', 'Ф8 Есть на Складе', 'файл'],
['подст:Nothost', 'Ф9 Файл — ВП:НЕХОСТИНГ' ],
['уд-пусткат', 'К1 Пустая категория' ],
['уд-перекат', 'К2 Переимен. кат.', 'категорию'],
['уд-владелец', 'У1 По запросу владельца' ],
['уд-анон', 'У2 Обсуждение анонима' ],
['уд-несущ', 'У3 Несуществующий участник' ],
['уд-нецелевое', 'У4 Нецелевое использование' ],
['уд-неактив', 'У5 Подстраница инактива' ]
],
/*
Генератор кода для меню на каждой странице
*/
menu = 'imp=КУЛ|rnm=КПМ|tRm=КУ|mRm=МНОГО КУ|ret=Оставить|noRnm=Не переименовано|fRm=КБУ|merge=КОБ|recov=ВУС|split=Разделить|'.replace(/(.*?)=(.*?)\|/g, '<li><a id=$1>$2</a></li>'),
/*
Селектор для темы Вектор, чтобы добавлять собственное выпадающее меню
*/
vector = $('#p-views'),
/*
Определение неймспейса
*/
ns = mw.config.get('wgNamespaceNumber'),
/*
Функция запроса к API.
Запрос бывает двух видов: edit и parse.
Чтоб каждый раз не передавать параметр, он — булева переменная
Токен и формат каждый раз дополняется перед запросом.
Токен и формат обязателен.
Аргументы:
1. Передаваемые параметры
2. Используемый режим
3. Колбек
void apiReq(object, bool, function(result, status))
*/
apiReq = function(param, mode, callback) {
param.format = 'json'
param.token = mw.user.tokens.get('editToken')
param.action =
mode == 0 ? 'edit' :
mode == 1 ? 'parse' : 'query'
$.post('/w/api.php', param, callback)
},
/*
Функция получения даты.
Необходимо, наример, для КУ-запросов.
Есть возможность указать собственную дату для подытоживания номинации.
['1051-32-33', '20 апреля 2014'] getDate(string)
*/
getDate = function(s) {
var d = (!!s) ? new Date(s) : new Date()
return [d.toISOString().substr(0, 10), d.getUTCDate() + ' ' +
'января,февраля,марта,апреля,мая,июня,июля,августа,сентября,октября,ноября,декабря'.split(',')[d.getUTCMonth()] +
' ' + d.getUTCFullYear()]
},
/*
Функция получения <input>
* Атрибут «h» используется в КБУ, указывая type
* Атрибут placeholder используется везде, для улучшения UI
* Атрибут id используется везде для получения информации из поля
string getInput(string, string, bool)
*/
getInput = function(id, p, h) {
return '<input id=' + id + ' type=' + (h ? 'hidden' : 'text') + ' placeholder="' + p + '" class=messagebox>'
},
/*
Функция получения текстов статьи и её СО
getTexts(string, string, function(string, string))
*/
getTexts = function(pg, pgtl, clbck) {
getText = {prop: 'wikitext'},
getText.page = pg
apiReq(getText, 1, function(txt1) {
getText.page = pgtl
apiReq(getText, 1, function(txt2) {
clbck(
txt1.parse ? txt1.parse.wikitext['*'] : '',
txt2.parse ? txt2.parse.wikitext['*'] : ''
)
})
})
},
/*
Функция отправки уведомления пользователю
По выполнению вызывает callback
userAlert(object, string, string, function())
*/
userAlert = function(param, pg, msg, clbck) {
apiReq({
prop: 'revisions',
rvprop: 'user',
rvdir: 'newer',
titles: pg
}, 2, function (t) {
i = t.query.pages
name = (typeof i['-1'] == 'undefined') ? i[Object.keys(i)[0]].revisions[0].user : ''
if (!/(\d{1,3}\.){3}\d/.test(name) && setAlert) {
apiReq({
title: 'оу:' + name,
section: 'new',
sectiontitle: param.sum,
summary: param.sum,
text: '~~\~~'
}, 0, function() {
clbck()
})
} else {
clbck()
}
})
}
/*
Функция работы с текстом статьи.
Получает адрес страницы обсуждения, получает тексты, определяет
необходимые шаблоны и устанавливает их на СО или статью.
changeArticle(object, string, string, function(string))
*/
changeArticle = function(param, pg, date, clbck) {
var so = mw.config.get( 'wgFormattedNamespaces' )[ns + 1] + ':' + pg.replace(/.*?:/, '')
getTexts(pg, so, function(article, talk) {
// Дописать остальные итоговые кнопочки и просто добавить. еще и привести в норм. состояние.
if (/(noRnm)/g.test(param[0])) { //не переименовано
var tpl = RegExp('(' + param[3].join('|') + ')\\|(\\d{4}-\\d\\d-\\d\\d)\\|?(.*?)}', 'gi').exec(article)
if (tpl == null)
location.reload()
date = getDate(tpl[2])
apiReq({
summary: param.sum.replace(/(\[В.*)\/.*?#/g, '$1/' + date[1] + '#'),
title: so,
text: '{\{' + param[4] + '|' + date[1] + '|' + pg + '|' + tpl[3] + '}}\n' + talk
}, 0)
article = article.replace(RegExp('(<noin.*?>)?{\{(' + param[3].join('|') + ').*?}}?(<\/noin.*?>)?', 'gi'), '')
}
if (/(ret)/g.test(param[0])) {//оставлено
var tpl = RegExp('(' + param[3].join('|') + ')\\|(\\d{4}-\\d\\d-\\d\\d)\\|?(.*?)}', 'gi').exec(article)
if (tpl == null)
location.reload()
date = getDate(tpl[2])
apiReq({
summary: param.sum.replace(/(\[В.*)\/.*?#/g, '$1/' + date[1] + '#'),
title: so,
text: '{\{' + param[4] + '|' + date[1] + '|' + tpl[3] + '}}\n' + talk
}, 0)
article = article.replace(RegExp('(<noin.*?>)?{\{(' + param[3].join('|') + ').*?}}?(<\/noin.*?>)?', 'gi'), '')
}
tpl = '<noinclude>{\{' +
(
param[0] == 'imp'
? 'подст:КУЛ'
: /(tRm|mRm)/g.test(param[0])
? 'К удалению|' + date[0]
: param[0] == 'fRm'
? fastRemove[$('#rmSel').val()][0] + '|' + $('#fiRm').val()
: param[0] == 'rnm'
? 'Кпм|' + date[0] + '|' + $('#rmHeader').val() + '|' + param.rmnNom
: param[0] == 'merge'
? 'subst:слить|' + $('#rmHeader').val()
: param[0] == 'split'
? 'split|' + date[0] + '|' + '[[' + $('#rmHeader').val() + ']] и [[' + $('#rmHeader2').val() + ']]'
: ''
) + '}}</noinclude>\n'
apiReq({
title: pg,
text: (tpl.length > 30 ? tpl : '') + article,
summary: param.sum
}, 0, function() {
clbck(pg)
})
})
},
/*
Функция установки номинации на соответствующую страницу
Аргументы:
1. Параметры
2. Заголовок номинации
3. Текст размещаемого сообщения
4. Колбек
void setNominate(param, section, msg, callback)
*/
setNominate = function(param, section, msg, callback) {
if (/(imp|rnm|tRm|mRm|merge|recov|split)/g.test(param[0])) {
apiReq({
title: param.place,
section: 'new',
sectiontitle:
'mRm' == param[0]
? section
: /(rnm|split|merge)/g.test(param[0])
? '[[:' + param.rmnNom.replace(/( → |, )/g, ']]$1[[:') + ']]'
: '[[:' + section + ']]',
summary: param.sum,
text: msg
}, 0, function() {
callback()
})
} else {
callback()
}
},
/*
Функция создания и обработки модального окна
void modalHandler(array)
*/
modalHandler = function(param) {
var content = ''
if (param[0] == 'mRm') {
content += getInput('rmHeader', 'Заголовок номинации')
for (i = 0; i < 5; i++) {
content += getInput('rmArticle' + i, 'Статья' + (i + 1))
}
}
if (param[0] == 'fRm') {
content += '<select id=rmSel class=messagebox>'
for (i = 0; i < fastRemove.length; i++) {
content += '<option value=' + i + '>' + fastRemove[i][1] + '</option>'
}
content += '</select>' + getInput('fiRm', '', 1)
}
if (param[0] == 'rnm') {
content += getInput('rmHeader', 'Новое название')
}
if (param[0] == 'merge') {
content += getInput('rmHeader', 'Объединить с…')
}
if (param[0] == 'split') {
content += getInput('rmHeader', 'Разделить на эту')
content += getInput('rmHeader2', 'И на эту')
}
if (/(imp|tRm|mRm|rnm|merge|recov|split)/g.test(param[0])) {
content += '<textarea id=rmMsg placeholder="Текст номинации без «~~\~~»." rows=4></textarea>'
}
$('#content').prepend(
'<div id=rmWindow style="padding:2em;margin:1em;border:1px solid #985; background: #fec;">' +
'<h1>' + param[1] + '</h1>' + content +
'<label><input name="rmUAlert" type=checkbox ' + ((setAlert) ? 'checked' : '') + '>Оповещать пользователя</label><br>' +
'<button id=rmBtn class=mw-ui-button>Отправить</button><button id=rmClose class=mw-ui-button>Отмена</button>'
)
$('#rmSel').change(function() {
i = fastRemove[this.value][2]
$('#fiRm').attr({type: (i ? 'text' : 'hidden'), placeholder: 'Укажите ' + i})
})
$('#rmClose').click(function() {
$('#rmWindow').remove()
})
$('#rmBtn').click(function() {
$('#rmWindow')
.append('<b class=mw-small-spinner></b>')
.children().attr('disabled', '1')
var date = getDate(),
msg = $('#rmMsg').val(),
wind = $('#rmWindow'),
pg = mw.config.get('wgPageName').replace(/_/g, ' '),
ttl = $('#rmHeader').val()
ttl2 = $('#rmHeader2').length ? $('#rmHeader2').val() : ''
param.place = param[2] ? 'ВП:' + param[2] + '/' + date[1] : ''
param.rmnNom = pg + ' → ' + ttl + (ttl2.length ? ', ' + $('#rmHeader2').val() : '')
param.sum = '[[у:higimo/remove.js|Удалятор]]: [[' + (param.place ? param.place + '#' : '') + pg + ']] — ' + param[1]
i = 0
setAlert = $('[name="rmUAlert"]').is(':checked')
if ($('#rmArticle0')[0]) {
i = 4
msg = '=== По всем ===\n' + msg
}
if (/(rnm|split|merge)/g.test(param[0])) {
param.sum = param.sum.replace(/#.*]]/g, '#' + param.rmnNom + ']]')
}
for (; i >= 0; i--) {
if ($('#rmArticle0')[0]) {
pg = $('#rmArticle' + i).val()
}
if (pg.length) {
if ($('#rmArticle0')[0]) {
param.sum = param.sum.replace(/#.*?\]/g, '#' + (ttl ? ttl : pg) + ']')
msg = '=== [[:' + pg + ']] ===\n' + msg
}
changeArticle(param, pg, date, function(pg) {
wind.append('Исправлена статья «' + pg + '»<br>')
userAlert(param, pg, msg + ' ~~\~~', function() {
wind.append('Уведомлен создатель<br>')
setNominate(param, (ttl ? ttl : pg), msg + ' ~~\~~', function() {
wind.append('Номинация записана<br>')
if (/(imp|rnm|tRm|mRm|recov|merge)/g.test(param[0])) {
wind.append('Открытие номинации<br>')
window.open(
'/wiki/' + param.place + '#' + encodeURI(pg.replace(/ /g, '_')).replace(/%/g, '.')
)
}
location.reload()
})
})
})
}
}
})
/*
Реализация ctrl+enter события
*/
$(window).keydown(function (e) {
if (e.ctrlKey && e.keyCode == 13)
$('#rmBtn').click()
})
}
/*
Добавление выпадающего меню на все страницы
*/
if (/\.([0-7]|1([0-1]([01])?|[45])?)\./g.test('.' + ns + '.')) {
if (vector.length) {
vector.after('<div class=vectorMenu><h3><span>Удалятор</span><a></a></h3><div class=menu><ul>' + menu + '</ul></div></div>')
} else {
$('#ca-history').after(menu)
}
}
/*
Событие по клику на любую кнопку выпадающего меню
*/
$('#imp,#tRm,#mRm,#ret,#fRm,#noRnm,#rnm,#merge,#recov,#split').click(function() {
i = this.id
modalHandler(
// [текущее действие, название модального окна и комментарий, название страницы, поддерживаемые шаблоны
i == 'imp' ? [ i, 'Номинация КУЛ', 'К улучшению' ] :
i == 'rnm' ? [ i, 'Номинация КПМ', 'К переименованию' ] :
i == 'tRm' ? [ i, 'Номинация КУ', 'К удалению' ] :
i == 'mRm' ? [ i, 'Номинация МНОГО КУ', 'К удалению' ] :
i == 'ret' ? [ i, 'Оставлено', 'К удалению', ['ку', 'к удалению'], 'Оставлено' ] :
i == 'noRnm'? [ i, 'Не переименовано', 'К переименованию', ['кпм', 'к переименованию'],'Не переименовано' ] :
i == 'merge'? [ i, 'Номинация КОБ', 'К объединению' ] :
i == 'recov'? [ i, 'Номинация ВУС', 'К восстановлению' ] :
i == 'split'? [ i, 'Номинация к разделению','К разделению' ] :
i == 'fRm' ? [ i, 'Номинация КБУ' ] : 0
)
})
})
Участник:Higimo/remove.js.