// ==UserScript==
// @name QuickPatrol_v2
// @namespace qp_tool_v2
// @version 2.30
// @description MediaWiki巡查工具 | A patrol tool for MediaWiki
// @author teaSummer
// @match *://*/wiki/*
// @match *://*/w/*
// @match *://*/index.php?*
// @license MIT
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @icon data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjY0IiBoZWlnaHQ9IjY0Ij4KPHBhdGggZD0iTTAgMCBDLTEuNDgyMzI2MzcgNC4xOTA4NzAzNyAtMy41ODgxNjg3OSA3LjU2Njg2ODUzIC02LjA2MjUgMTEuMjUgQy0xNC4yOTA3MTcxNCAyMy43OTYzMTAyOCAtMjAuNzgzMjk3MDMgMzYuOTQ1NTg4NDYgLTI2IDUxIEMtMjguODIyNzg0MTcgNTEuMjEwMTc2MjggLTMxLjIyNDQxNTI3IDUxLjM4NDA1MTY3IC0zNCA1MSBDLTM2LjA2NjQwNjI1IDQ5LjA5Mzc1IC0zNi4wNjY0MDYyNSA0OS4wOTM3NSAtMzcuNTYyNSA0Ni41IEMtNDAuMjY5ODgxNjYgNDIuMTAyMDY0MzUgLTQzLjE2MjMzNzgyIDM4LjQzMTI5NzExIC00Ni43MTQ4NDM3NSAzNC42OTE0MDYyNSBDLTQ4IDMzIC00OCAzMyAtNDggMzAgQy00NS4wOTg5NjczNiAyOC41NDk0ODM2OCAtNDMuMjE0OTAyNzYgMjguNTkyMTk4MyAtNDAgMjkgQy0zNy41MTU2MjUgMzEuMzcxMDkzNzUgLTM3LjUxNTYyNSAzMS4zNzEwOTM3NSAtMzUuMjUgMzQuNDM3NSBDLTMyLjYxNjA1MTQxIDM4LjI5NDUyODk1IC0zMi42MTYwNTE0MSAzOC4yOTQ1Mjg5NSAtMjkgNDEgQy0yOC44NjA3ODEyNSA0MC4wMjE2MDE1NiAtMjguODYwNzgxMjUgNDAuMDIxNjAxNTYgLTI4LjcxODc1IDM5LjAyMzQzNzUgQy0yNy43NjIzOTM4MSAzNS4wMDA1MDQ0MSAtMjYuMTgyMDY0MDkgMzEuMzkzNjA5MjcgLTI0LjUgMjcuNjI1IEMtMjQuMTQ5MDUyNzMgMjYuODM4NTkxMzEgLTIzLjc5ODEwNTQ3IDI2LjA1MjE4MjYyIC0yMy40MzY1MjM0NCAyNS4yNDE5NDMzNiBDLTIwLjk3MzE4NTg5IDE5Ljg1MTM1Nzc4IC0xOC4yNzUwODM4OSAxNC42NTg3NzgyNyAtMTUuMjUgOS41NjI1IEMtMTQuODg1ODM5ODQgOC45NDI2MjIwNyAtMTQuNTIxNjc5NjkgOC4zMjI3NDQxNCAtMTQuMTQ2NDg0MzggNy42ODQwODIwMyBDLTEwLjE4MDg3NDY3IDEuMjE1NDk4MzcgLTcuNjA4MTM4NTQgLTAuNDM4OTMxMDcgMCAwIFogIiBmaWxsPSIjMDA4MDAwIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg1Niw3KSIvPgo8cGF0aCBkPSJNMCAwIEMwLjk5IDAuMzMgMS45OCAwLjY2IDMgMSBDMyAyLjMyIDMgMy42NCAzIDUgQzQuMzIgNSA1LjY0IDUgNyA1IEM3IDUuNjYgNyA2LjMyIDcgNyBDNS42OCA3IDQuMzYgNyAzIDcgQzIuNjcgOC42NSAyLjM0IDEwLjMgMiAxMiBDMS4zNCAxMiAwLjY4IDEyIDAgMTIgQzAgMTAuMzUgMCA4LjcgMCA3IEMtMS42NSA3IC0zLjMgNyAtNSA3IEMtNSA2LjM0IC01IDUuNjggLTUgNSBDLTMuMzUgNSAtMS43IDUgMCA1IEMwIDMuMzUgMCAxLjcgMCAwIFogIiBmaWxsPSIjRjFGRjBFIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg1NSwxNikiLz4KPC9zdmc+Cg==
// ==/UserScript==
(() => {
'use strict';
// 本地化 | Localization
const w = {
'en': {
un: 'This edit has not yet been patrolled',
ing: 'Quick patrolling...',
done: 'Quick patrolled',
t_un: 'Unpatrolled',
g_un: 'Unpatrolled',
hl: 'Highlighted: ',
s: 'Additional summary:',
h_1: 'Apply',
h_2: '[[Special:AbuseLog/$1|AbuseLog/$1]] by [[Special:Contribs/$2|$2]] ([[User talk:$2|talk]]), ',
h_3: 'the original summary is "$1"',
h_4: 'no original summary',
g_cr_1: 'Sure to rollback this edit?',
g_er_1: 'Revert edits by [[Special:Contribs/$1|$1]] ([[User talk:$1|talk]])',
g_er_2: 'Edit rollback summary',
c: ': ',
n_1: '✔ Applied',
n_2: '× Failed to apply',
n_3: '⚙️ Settings',
n_4: 'Patrol all logs (in emergency)',
r_summary: 'Summary',
r_confirm: 'Confirm',
r_default: 'Default',
qp_patrol: 'Quick Patrol',
qp_rollback: 'Quick Rollback',
qp_rollback_mode: 'Rollback Mode',
qp_abuse_edit: 'Helper that Filtered Edits',
qp_jump_blank: 'Links Open in New Tabs',
qp_using_ooui: 'Using OOUI',
qp_max_retries: 'Maximum Retries of Initialization',
qp_local_summary: 'Localization Maps English Summary',
map: ['unnecessary edit', 'unnecessary information|unnecessary content|unnecessary info|unnecessary|#UN#|#U#',
'false content', 'false information|false info|false|#F#',
'outdated content', 'outdated information|outdated info|outdated?|#OUT#|#OD#|#O#',
'machine translation', 'machine-trans|#MT#',
'duplicated content', 'duplicated information|duplicated info|duplicated?|#DUP#|#DP#|#D#',
'unambiguous content', 'unambig(uous)?|#NAM#|#NA#',
'ambiguous content', 'ambig(uous)?|#AM#',
'WAI for content', '(sic|WAI)( content|-C)|#SIC#|#SC#|#S#',
'Works As Intended', '#WAI#|WAI|#W#',
'N-ST', '#NST#|#NS#',
'refuse moving', 'refuse deleting', 'refuse',
'keeping redirection after moving', 'keeping redirection', 'typo',
'sic', 'fixed', 'fix']
},
'zh-hans': {
un: '该编辑尚未巡查',
ing: '快速巡查中…',
done: '已快速巡查',
t_un: '未巡查',
g_un: '尚未巡查',
hl: '已高亮:',
s: '附加摘要:',
h_1: '应用',
h_2: '[[Special:AbuseLog/$1|滥用日志/$1]] — [[Special:Contribs/$2|$2]]([[User talk:$2|留言]]),',
h_3: '原始摘要为“$1”',
h_4: '没有原始摘要',
g_cr_1: '确定要回退此编辑吗?',
g_er_1: '回退[[Special:Contribs/$1|$1]]([[User talk:$1|留言]])所做的编辑',
g_er_2: '编辑回退摘要',
c: ':',
n_1: '✔ 应用完成',
n_2: '× 应用失败',
n_3: '⚙️ 设置',
n_4: '巡查所有日志(紧急时)',
r_summary: '摘要',
r_confirm: '确认',
r_default: '默认',
qp_patrol: '快速巡查',
qp_rollback: '快速回退',
qp_rollback_mode: '回退模式',
qp_abuse_edit: '过滤内容编辑助手',
qp_jump_blank: '在新标签页打开链接',
qp_using_ooui: '使用OOUI',
qp_max_retries: '初始化最大重试次数',
qp_local_summary: '本地化映射英语摘要',
map: ['不必要的编辑', '不必要的编辑', //
'含不实内容', '含不实内容', //
'含过时内容', '含过时内容', //
'疑似使用机器翻译', '疑似使用机器翻译', //
'内容重复', '内容重复', //
'内容无歧义', '内容无歧义', //
'内容含有歧义', '内容含有歧义', //
'原文无误', '原文无误', //
'有意为之', '有意为之', //
'含非标准译名的编辑', '含非标准译名的编辑', //
'拒绝移动', '拒绝删除', '拒绝',
'移动后保留重定向', '保留重定向', '含错误拼写的编辑',
'原文如此', '已修复', '修复']
},
'zh-hant': {
un: '該編輯尚未巡查',
ing: '快速巡查中…',
done: '已快速巡查',
t_un: '未巡查',
g_un: '尚未巡查',
hl: '已明顯標示:',
s: '附加摘要:',
h_1: '應用',
h_2: '[[Special:AbuseLog/$1|濫用日誌/$1]] — [[Special:Contribs/$2|$2]]([[User talk:$2|留言]]),',
h_3: '原始摘要為「$1」',
h_4: '沒有原始摘要',
g_cr_1: '確定要回退此編輯嗎?',
g_er_1: '回退[[Special:Contribs/$1|$1]]([[User talk:$1|留言]])所做的編輯',
g_er_2: '編輯回退摘要',
c: ':',
n_1: '✔ 應用完成',
n_2: '× 應用失敗',
n_3: '⚙️ 設定',
n_4: '巡查所有日誌(緊急時)',
r_summary: '摘要',
r_confirm: '確認',
r_default: '預設',
qp_patrol: '快速巡查',
qp_rollback: '快速回退',
qp_rollback_mode: '回退模式',
qp_abuse_edit: '過濾內容編輯助手',
qp_jump_blank: '在新標籤頁開啟連結',
qp_using_ooui: '使用OOUI',
qp_max_retries: '初始化最大重試次數',
qp_local_summary: '本地化對映英語摘要',
map: ['不必要的編輯', '不必要的編輯', //
'含不實內容', '含不實內容', //
'含過時內容', '含過時內容', //
'疑似使用機器翻譯', '疑似使用機器翻譯', //
'內容重複', '內容重複', //
'內容無歧義', '內容無歧義', //
'內容含有歧義', '內容含有歧義', //
'原文無誤', '原文無誤', //
'有意為之', '有意為之', //
'含非標準譯名的編輯', '含非標準譯名的編輯', //
'拒絕移動', '拒絕刪除', '拒絕',
'移動後保留重定向', '保留重定向', '含錯誤拼寫的編輯',
'原文如此', '已修復', '修復']
}
};
// ES2017 -> ES2015
function asyncGeneratorStep(ag_n, ag_t, ag_e, ag_r, ag_o, ag_a, ag_c) { let ag_i, ag_u; try { ag_i = ag_n[ag_a](ag_c); ag_u = ag_i.value; } catch (n) { return void ag_e(n); } return ag_i.done ? ag_t(ag_u) : Promise.resolve(ag_u).then(ag_r, ag_o); }
function _asyncToGenerator(ag_n) { return function () { let ag_t = this, ag_e = arguments, ag_a; return new Promise(function (r, o) { ag_a = ag_n.apply(ag_t, ag_e); function _next(n) { asyncGeneratorStep(ag_a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(ag_a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
const $E = (e, f = void 0, r = void 0) => {
if ($(e).length) return typeof f == 'function' ? f($(e)) : $(e);
return typeof f == 'function' ? r : f;
};
const status = {};
let mwApi, mwLang, rights, l, fail = 0, load = false;
status.np = '.mw-changeslist-reviewstatus-unpatrolled:not(.mw-rcfilters-ui-highlights-enhanced-toplevel):not(.quickpatrol), .revisionpatrol-unpatrolled';
status.load = _asyncToGenerator(function* (...l) {
for (let f of l) yield mw.loader.load(`https://fastly.jsdelivr.net/gh/teaSummer/QuickPatrol_v2@${f}`, f.endsWith('.css') ? 'text/css' : void 0);
});
function helper() {
if (!$E('.mw-abuselog-details')) return;
const g = (e) => $E(`.mw-abuselog-details-${e} div.mw-abuselog-var-value`, (e) => e.text().replace(/^'|'$/g, ''));
const v = {
user_name: g('user_name'),
action: g('action'),
summary: g('summary'),
new_wikitext: g('new_wikitext'),
page_prefixedtitle: g('page_prefixedtitle'),
lgid: location.href.replace(/\/+$/, '').split('/').slice(-1)[0].replace(/[^0-9]/g, ''),
created: $E('fieldset .mw-usertoollinks+a.new')
};
if (v.action != 'edit') return;
let o_summary = l.h_2.replace(/\$1/g, v.lgid).replace(/\$2/g, v.user_name);
$('#mw-content-text p').after(`<button class="quickpatrol-abuseedit">${l.h_1}</button>`);
o_summary = o_summary + (v.summary ? l.h_3.replace('$1', v.summary) : l.h_4);
if (v.summary.trim()) {
$('.quickpatrol-abuseedit').after(`<div class="quickpatrol-abuseedit-summary"/>`);
$('.quickpatrol-abuseedit-summary').text(v.summary);
}
$E('.diff-type-table', $('.quickpatrol-abuseedit-summary')).after('<textarea class="new_wikitext" cols="80" rows="25"/>');
$('.new_wikitext').val(v.new_wikitext).before('<input class="page_prefixedtitle"/>');
if (mw.addWikiEditor) mw.addWikiEditor($('.new_wikitext'));
$('.page_prefixedtitle').val(v.page_prefixedtitle).attr('placeholder', v.page_prefixedtitle);
$('.mw-abuselog-details').wrap(`<details/>`);
$('.quickpatrol-abuseedit').click(function () {
const me = $(this);
const rb = (result) => {
let act;
const r = result.trim();
const title = $E('.page_prefixedtitle', (e) => e.val() ? e.val() : v.page_prefixedtitle, v.page_prefixedtitle);
const summary = r ? o_summary + l.c + r : o_summary;
const text = $E('.new_wikitext', (e) => e.val(), v.new_wikitext);
const notice = summary.replace(/\[\[[^|[\]]*\|(.*?)]]/g, '$1');
me.attr('disabled', true);
$(window).on('beforeunload', () => me.attr('disabled'));
if (!v.created) {
act = mwApi.edit(title, () => Object({
summary: summary,
text: text,
minor: true
}));
} else {
act = mwApi.create(title, { summary: summary }, text);
}
act.done(() => {
me.remove();
$(window).off('beforeunload');
mw.notify(notice, { title: l.n_1, type: 'success' });
}).fail(() => {
me.removeAttr('disabled');
mw.notify(notice, { title: l.n_2, type: 'error' });
});
};
if (status.ooui) OO.ui.prompt(l.s).done(rb);
else {
const result = prompt(l.s);
if (result != null) rb(result);
}
});
}
function g_cr() {
$('.mw-rollback-link a:not(.quickpatrol-rollback)').each(function () {
const href = $(this).attr('href');
$(this).click((e) => {
e.preventDefault();
if (status.ooui) {
OO.ui.confirm(l.g_cr_1).done((confirmed) => {
if (confirmed) location.href = href;
});
} else if (confirm(l.g_cr_1)) location.href = href;
});
status.rf(this);
});
}
function g_er(p) {
let el = '.mw-rollback-link a';
if (p) {
if (p == 2) g_cr();
$(el).each(function () {
$(this).after($(`<span class="edit-rollback" href="${$(this).attr('href')}" title="${l.g_er_2}"></span>`));
status.rf(this);
});
el = '.edit-rollback';
}
el = `${el}:not(.quickpatrol-rollback)`;
$(el).each(function () {
const href = $(this).attr('href');
$(this).click((e) => {
e.preventDefault();
const rb = (result) => {
let r = result.trim();
if (GM_getValue('qp_local_summary')) {
Object.entries(w).forEach(([k, v]) => {
for (let i = 0; i < v.map.length; i++) r = r.replace(new RegExp(`\\b${v.map[i]}\\b`, 'gi'), l.map[i]);
});
}
location.href = href + '&summary=' + encodeURIComponent(r ? summary + l.c + r : summary);
};
const name = decodeURIComponent(href.match(/&from=(.+)&token/)[1].replace(/\+/g, ' '));
const summary = mw.format(l.g_er_1, name);
if (status.ooui) OO.ui.prompt(l.s).done(rb);
else {
const result = prompt(l.s);
if (result != null) rb(result);
}
});
status.rf(this);
});
}
function rollback_util() {
if (GM_getValue('qp_rollback_mode') == 'd' || !load) return;
if (!(OO && OO.ui && OO.ui.confirm)) status.ooui = false;
load[0](load[1]);
}
function init() {
_asyncToGenerator(function* () {
const defaultValue = {
qp_patrol: true,
qp_rollback: true,
qp_rollback_mode: 's',
qp_abuse_edit: true,
qp_jump_blank: false,
qp_using_ooui: true,
qp_max_retries: 10,
qp_local_summary: false
};
Object.entries(defaultValue).forEach(([k, v]) => {
if (GM_getValue(k) == void 0) GM_setValue(k, v);
});
if (fail >= GM_getValue('qp_max_retries')) return;
try {
mwApi = yield new mw.Api();
mwLang = Object.keys(yield mw.language.data)[0];
if (['zh-cn', 'zh-hans', 'zh-hans-cn', 'zh'].includes(mwLang)) mwLang = 'zh-hans';
else if (mwLang.startsWith('zh-')) mwLang = 'zh-hant';
if (!Object.keys(w).includes(mwLang)) mwLang = 'en';
l = w[mwLang];
if (load) return;
load = true;
status.ooui = GM_getValue('qp_using_ooui');
GM_registerMenuCommand(l.n_3, () => {
let html = `<div class="quickpatrol-setting">
<label>${l.qp_patrol}<input type="checkbox" id="quickpatrol-option-patrol" ${GM_getValue('qp_patrol') ? 'checked' : ''}></label>
<label>${l.qp_rollback}<input type="checkbox" id="quickpatrol-option-rollback" ${GM_getValue('qp_rollback') ? 'checked' : ''}></label>
<label>${l.qp_rollback_mode}<select id="quickpatrol-option-rollback-mode">
<option value="s" ${GM_getValue('qp_rollback_mode') == 's' ? 'selected' : ''}>${l.r_summary}</option>
<option value="c" ${GM_getValue('qp_rollback_mode') == 'c' ? 'selected' : ''}>${l.r_confirm}</option>
<option value="d" ${GM_getValue('qp_rollback_mode') == 'd' ? 'selected' : ''}>${l.r_default}</option>
<option value="c+s" ${GM_getValue('qp_rollback_mode') == 'c+s' ? 'selected' : ''}>${l.r_confirm}+${l.r_summary}</option>
<option value="d+s" ${GM_getValue('qp_rollback_mode') == 'd+s' ? 'selected' : ''}>${l.r_default}+${l.r_summary}</option>
</select></label>
<label>${l.qp_abuse_edit}<input type="checkbox" id="quickpatrol-option-abuse-edit" ${GM_getValue('qp_abuse_edit') ? 'checked' : ''}></label>
<label>${l.qp_jump_blank}<input type="checkbox" id="quickpatrol-option-jump-blank" ${GM_getValue('qp_jump_blank') ? 'checked' : ''}></label>
<label>${l.qp_using_ooui}<input type="checkbox" id="quickpatrol-option-using-ooui" ${GM_getValue('qp_using_ooui') ? 'checked' : ''}></label>
<label>${l.qp_max_retries}<input type="range" min="1" max="20" id="quickpatrol-option-max-retries" value="${GM_getValue('qp_max_retries')}"><span>${GM_getValue('qp_max_retries')}</span></label>
<label>${l.qp_local_summary}<input type="checkbox" id="quickpatrol-option-local-summary" ${GM_getValue('qp_local_summary') ? 'checked' : ''}></label>
</div>`;
Swal.fire({
html,
showCloseButton: true,
confirmButtonText: l.h_1
}).then((res) => {
if (!res.isConfirmed) return;
Object.entries(defaultValue).forEach(([k, v]) => {
const e = $('#quickpatrol-option-' + k.slice(3).replace(/_/g, '-'));
GM_setValue(k, typeof v == 'boolean' ? e.is(':checked') : e.val());
});
location.reload();
});
$('#quickpatrol-option-max-retries').on('input', function () {
$(this).find('+span').text($(this).val());
});
$('#quickpatrol-option-rollback').change(function () {
$('#quickpatrol-option-rollback-mode').attr('disabled', !$(this).is(':checked'));
});
});
$E('.mw-changeslist', () => GM_registerMenuCommand(l.n_4, () => {
if (status.ooui) {
OO.ui.confirm(l.n_4).done((confirmed) => {
if (confirmed) $('[data-mw-logid] .unpatrolled').trigger('click');
});
} else if (confirm(l.n_4)) $('[data-mw-logid] .unpatrolled').trigger('click');
}));
const oe = ['.mw-changeslist', '#mw-diff-ntitle1 strong', '#mw-diff-otitle1 strong', '.mw-contributions-list li'];
const ob_IPE = new MutationObserver(with_IPE);
const ob = new MutationObserver((ml) => {
ml.forEach((m) => {
const t = $(m.target);
if (t.attr('class').includes('revisionpatrol-') || t.hasClass('mw-changeslist')) main();
$E(m.addedNodes, (e) => {
if (e.hasClass('quick-diff')) ob_IPE.observe(e.find('.ipe-progress')[0], { attributes: true });
});
});
});
ob.observe(document.body, { childList: true });
for (let x of oe) $E(x, (e) => ob.observe(e[0], { childList: true, attributes: true }));
status.load('main/styles.css', `minecraft-wiki/patrol/${mwLang}/Gadget-revisionPatrol.css`, `minecraft-wiki/patrol/${mwLang}/Gadget-revisionPatrol.js`);
mw.loader.load('https://unpkg.com/[email protected]/dist/sweetalert2.min.js');
mw.loader.load('https://unpkg.com/[email protected]/dist/sweetalert2.min.css', 'text/css');
load = ((m) => m == 's' ? [g_er] : m == 'c' ? [g_cr] : m == 'd+s' ? [g_er, 1] : m == 'c+s' ? [g_er, 2] : null)(GM_getValue('qp_rollback_mode'));
if (load.length == 2) status.load(`minecraft-wiki/rollback/${mwLang}/Gadget-editableRollback.css`);
} catch (e) {
fail = fail + 1;
if (fail < GM_getValue('qp_max_retries')) console.warn(`[QuickPatrol] Failed to call MediaWiki. Retrying... (${fail}/${GM_getValue('qp_max_retries')})`);
else console.error(`[QuickPatrol] Failed to call MediaWiki. (${fail}/${GM_getValue('qp_max_retries')})`);
new Promise(() => setTimeout(init, 2000));
return;
}
console.log('[QuickPatrol] Checking rights...');
rights = (yield mwApi.post({
action: 'query',
meta: 'userinfo',
uiprop: 'rights'
})).query.userinfo.rights;
Object.assign(status, {
patrol: rights.includes('patrol') && GM_getValue('qp_patrol'),
rollback: rights.includes('rollback') && GM_getValue('qp_rollback'),
abuselog: rights.includes('abusefilter-log-detail') && GM_getValue('qp_abuse_edit'),
rf: (e) => $(e).addClass(`quickpatrol-rollback ${mwLang.startsWith('zh-') ? 'consolas' : ''}`)
});
if (GM_getValue('qp_jump_blank')) $('.interlanguage-link-target, .vector-menu-content .selected a, #p-personal a, #mw-panel a:not([href^="#"]), a:not([href^="#"],[href$="/doc"],[href*="section="],:has(span))').attr('target', '_blank');
main();
})();
}
function with_IPE() {
if (!status.patrol) return;
$('.diff-version:not(.diff-hidden-history)').click(function () {
const me = $(this);
if (me.attr('title')) return;
const revid = me.text().replace(/[^0-9]/g, '');
me.addClass('patrolling').attr('title', l.ing);
patrol(me, revid);
});
}
function main() {
if (!rights) {
if (fail >= GM_getValue('qp_max_retries') || !fail) init();
return;
}
if (status.abuselog) helper();
if (status.rollback) rollback_util();
if (!status.patrol) return;
$(status.np).each(function () {
const that = $(this);
that.find('.revisionpatrol-icon-unpatrolled').after(`<span class="unpatrolled quickpatrol-icon-unpatrolled" title="${l.g_un}">!</span>`);
that.find('.revisionpatrol-icon-unpatrolled').remove();
that.find('.unpatrolled').addClass('quickpatrol').click(_asyncToGenerator(function* () {
const me = $(this);
if (me.text() != '!') return;
me.addClass('patrolling').removeClass('unpatrolled');
$(this).text('#').attr('title', l.ing);
let revid = that.attr('data-mw-revid');
if (that.attr('data-mw-logid')) {
yield mwApi.post({
action: 'query',
list: 'logevents',
leprop: 'ids',
letitle: that.find('td.mw-enhanced-rc-nested').attr('data-target-page'),
letype: that.attr('data-mw-logaction').split('/')[0],
lelimit: 'max',
format: 'json'
}).done((data) => {
const q = data.query.logevents.find((i) => i.logid == that.attr('data-mw-logid'));
if (q) revid = q.revid;
});
}
if (!revid) return $(this).text('!').addClass('unpatrolled').removeClass('patrolling').attr('title', l.un);
that.attr('data-mw-revid', revid);
patrol(me, revid);
}));
});
}
function patrol(me, revid, rcid = void 0) {
const success = () => {
if (!rcid) console.debug(`[QuickPatrol] SUCCEEDED (revid: ${revid})`);
me.text('✔').addClass('quickpatrol').removeClass('patrolling unpatrolled').attr('title', l.done).off('click');
const that = $(`[data-mw-revid=${revid}]`);
const clear = (e) => {
$E(`.mw-rcfilters-ui-filterTagItemWidget:contains(${l.t_un}) .mw-rcfilters-ui-tagItemWidget-highlight`, (c) => {
e.removeClass(`mw-rcfilters-highlight-color-${c.data('color')}`);
});
e.removeClass('mw-changeslist-reviewstatus-unpatrolled');
e.attr('title', e.attr('title').replace(new RegExp(`(, |、\u200B)?${l.t_un}(、\u200B|, )?`, 'g'), ''));
if (e.attr('title') == l.hl) e.removeClass('mw-rcfilters-ui-changesListWrapperWidget-enhanced-grey').removeAttr('title');
e.find('.unpatrolled').text('✔').addClass('quickpatrol').removeClass('unpatrolled').attr('title', l.done).off('click');
};
clear(that);
$E(that.parent().find('.mw-rcfilters-ui-highlights-enhanced-toplevel'), (e) => {
if (!$E(e.siblings().find('.unpatrolled, .patrolling'))) clear(e);
});
};
const fail = () => {
const f = () => {
console.warn(`[QuickPatrol] FAILED (revid: ${revid})`);
me.text('!').addClass('unpatrolled').removeClass('patrolling').attr('title', l.un);
if (me.hasClass('quickpatrol-icon-unpatrolled')) me.attr('title', l.g_un);
};
mwApi.post({
action: 'query',
list: 'recentchanges',
rcprop: 'ids',
rctitle: me.parent().parent().find('td.mw-enhanced-rc-nested').attr('data-target-page'),
rclimit: 'max',
format: 'json'
}).done((data) => {
const q = data.query.recentchanges.find((i) => i.revid == revid);
if (!q) return f();
patrol(me, revid, q.rcid);
}).fail(f);
};
if (!rcid) console.debug(`[QuickPatrol] TRYING (revid: ${revid})`);
mwApi.post({
action: 'query',
meta: 'tokens',
type: 'patrol',
format: 'json'
}).done((data) => {
mwApi.post({
action: 'patrol',
token: data.query.tokens.patroltoken,
format: 'json',
[rcid ? 'rcid' : 'revid']: rcid || revid
}).done(success).fail(fail);
}).fail(fail);
}
init();
})();