// ==UserScript==
// @name QuickPatrol_v2
// @namespace qp_tool_v2
// @version 1.78
// @description MediaWiki巡查工具 | A patrol tool for MediaWiki
// @author teaSummer
// @match *://*/wiki/*
// @match *://*/w/*
// @match *://*/index.php?*
// @license MIT
// @grant none
// ==/UserScript==
(function () {
'use strict';
// 配置 | Configuration
const config = {
liveUpdate: false, // 全局实时更新 | Global Live Update
liveUpdateInterval: 1000, // 全局实时更新间隔(毫秒) | Global Live Update Interval (Millisecond)
usingIPE: false, // 使用InPageEdit | Using InPageEdit
maxRetries: 5 // 获取mwApi最大重试次数 | Maximum Retries of Getting mwApi
};
let mwApi, rights, fail = 0;
const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay));
async function init() {
if (fail >= config.maxRetries) return;
try {
mwApi = new mw.Api();
} catch (e) {
fail = fail + 1;
console[fail < config.maxRetries ? "warn" : "error"](`[QuickPatrol] Failed to get mwApi. Will try again in 1.0s (${fail}/${config.maxRetries}).`);
return await sleep(1000, init);
}
console.log('[QuickPatrol] Checking rights...');
rights = (
await mwApi.get({
action: 'query',
meta: 'userinfo',
uiprop: 'rights',
})
).query.userinfo.rights;
if (!config.liveUpdate) main();
return;
}
function with_IPE() {
$('.diff-version:not([title])').css({ color: 'blue', cursor: 'pointer' });
$('.diff-version').click(function () {
const me = $(this);
if (me.attr('title')) return;
const value = me.text().replace(/[^0-9]/g, '');
$(this).css('color', 'deeppink').attr('title', '快速巡查中…');
patrol(
value,
() => {
me.text('✔')
.css({
color: 'green',
cursor: 'default',
})
.attr('title', '已快速巡查');
}
);
return value;
});
}
async function main() {
if (!rights) {
init();
return;
}
if (rights.includes('patrol')) {
$('.mw-changeslist-reviewstatus-unpatrolled:not(.mw-rcfilters-ui-highlights-enhanced-toplevel), .revisionpatrol-unpatrolled').attr('data-mw-revid', function (_i, value) {
const that = $(this);
that.find('.revisionpatrol-icon-unpatrolled').after('<span class="unpatrolled custom-unpatrolled" title="该编辑尚未巡查">!</span>');
that.find('.revisionpatrol-icon-unpatrolled+.custom-unpatrolled').css({
color: 'red',
'font-weight': 'bold',
position: 'absolute',
left: '-0.8em',
'margin-left': '-1px',
'text-decoration': 'underline dotted'
});
that.find('.revisionpatrol-icon-unpatrolled').remove();
that.find('.unpatrolled')
.css('cursor', 'pointer')
.click(async function () {
let me = $(this);
if (me.hasClass('custom-unpatrolled')) me.css('left', '-1em');
if (me.text() == '!') {
$(this).text('#').css('color', 'magenta').attr('title', '快速巡查中…');
if (!value && that.attr('data-mw-logid')) {
try {
value = new RegExp(`"logid":${that.attr('data-mw-logid')},.+?,"revid":([0-9]+)`).exec(JSON.stringify((await mwApi
.get({
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',
})
)))[1];
} catch (e) {
$(this).text('!').css('color', 'red').attr('title', '该编辑尚未巡查');
return;
}
}
patrol(
value,
() => {
me.text('✔')
.css({
color: 'green',
cursor: 'default',
})
.attr('title', '已快速巡查').removeClass('unpatrolled');
if (me.hasClass('custom-unpatrolled')) {
me.css({
left: '-1.15em',
'font-weight': 'normal'
});
} else {
me.css('margin-left', '-0.1em');
}
that.removeClass('mw-rcfilters-highlight-color-c5').removeClass('mw-changeslist-reviewstatus-unpatrolled');
that.attr('title', that.attr('title').replace(/、?\u200B?未巡查、?\u200B?/g, ''));
if (that.attr('title') == '已高亮:') that.removeAttr('title');
},
() => { if (me.hasClass('custom-unpatrolled')) me.css('left', '-0.8em') }
);
}
});
return value;
});
if (config.usingIPE) with_IPE();
}
}
function patrol(revid, successFallback, exFailFallback = () => { }) {
const failFallback = () => {
console.warn(`[QuickPatrol] FAILED (revid: ${value})`);
me.text('!').css('color', 'red').attr('title', '该编辑尚未巡查');
exFailFallback();
}
console.debug(`[QuickPatrol] TRYING (revid: ${revid})`);
mwApi
.get({
action: 'query',
meta: 'tokens',
type: 'patrol',
format: 'json',
})
.done((data) => {
mwApi
.post({
action: 'patrol',
revid: revid,
token: data.query.tokens.patroltoken,
format: 'json',
})
.done(() => {
console.debug(`[QuickPatrol] SUCCEEDED (revid: ${revid})`);
successFallback();
})
.fail(failFallback);
})
.fail(failFallback);
}
window.addEventListener('load', init, false);
if (config.liveUpdate) {
window.setInterval(main, config.liveUpdateInterval);
} else if (config.usingIPE) {
window.setInterval(with_IPE, config.liveUpdateInterval);
}
})();