User:Bluedeck/source/ar-admin-3.js
外观
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google Chrome、Firefox、Microsoft Edge及Safari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
// 本工具暂无用户界面。若要使用,可复制到console,并手动调用:
// await bluedeck_ar_version_3_fm3osisn4diqncu28("页面名称");
async function bluedeck_ar_version_3_fm3osisn4diqncu28(pagename) {
const WIKI_HOST = "https://zh.wikipedia.org";
const REMOTE_HOST = "https://minigun.app";
const X_WWW_FORM_URLENCODED = { headers: { "Content-Type": "application/x-www-form-urlencoded" } };
const POST = { method: "POST" };
const minigun_link = (case_number, revid) => `https://minigun.app/@bluedeck/zhwp/arview/id/${enc(case_number)}/rev.${enc(revid)}/contentplain`;
const enc = encodeURIComponent;
// main proc starts
const revisions = await main_arproc_read(pagename);
const index_page = await main_arproc_write(pagename, revisions);
// main proc ends
/** @template T @param {T[]} arr @param {number} number @returns {T[][]} */
function arrgroup(arr, number) {
const grouped = [];
for (let i=0; i<arr.length; i++) {
if (i % number === 0) { grouped.push([]); }
grouped[grouped.length-1].push(arr[i]);
}
return grouped;
}
/** @returns {Promise<string>} */
async function load_token() {
const token_obj = await (await fetch(WIKI_HOST + `/w/api.php?action=query&meta=tokens&format=json`, { ...POST, ...X_WWW_FORM_URLENCODED })).json();
return token_obj.query.tokens.csrftoken;
}
/** @param {string} a @returns {string} */
function replace_string_escape_wikitext(a){
return a.replaceAll("<", "<").replaceAll("{{", "<nowiki>{{</nowiki>").replaceAll("~~", "~<!---->~").replaceAll("[[", "[[:").replaceAll("[[::", "[[:");
}
/** @param {string} pgname @param {string} newcontent @param {string} summary @param {string} token @returns {Promise<void>} */
async function asyncfetchedit(pgname, newcontent, summary, token) {
const body = `action=edit&bot=1&format=json&title=${enc(pgname)}&text=${enc(newcontent)}&summary=${enc(summary)}&token=${enc(token)}`;
await fetch(WIKI_HOST + `/w/api.php`, { ...POST, ...X_WWW_FORM_URLENCODED, body });
}
/** @param {string} pagename @returns {Promise<Array>} */
async function main_arproc_read(pagename) {
console.log(` ---------- Starting loading [[${pagename}]] ---------- `);
let prerevlist = await (await fetch(WIKI_HOST + `/w/api.php?action=query&prop=deletedrevisions&format=json&drvprop=content|comment|user|userid|timestamp|size|ids&drvlimit=100&titles=${enc(pagename)}`, { ...POST, ...X_WWW_FORM_URLENCODED })).json();
let revlist=[];
while(prerevlist["continue"]) {
revlist=Object.entries(prerevlist.query.pages)[0][1].deletedrevisions.toReversed().concat(revlist);
prerevlist = await (await fetch(WIKI_HOST + `/w/api.php?action=query&prop=deletedrevisions&format=json&drvprop=content|comment|user|userid|timestamp|size|ids&drvlimit=100&titles=${enc(pagename)}&drvcontinue=${enc(prerevlist["continue"].drvcontinue)}`, { ...POST, ...X_WWW_FORM_URLENCODED })).json();
}
revlist=Object.entries(prerevlist.query.pages)[0][1].deletedrevisions.toReversed().concat(revlist);
console.log(` ---------- Finished loading ${revlist.length} deleted revisions for [[${pagename}]] ---------- `);
return revlist;
}
/** @param {Array} revisions must conform to the minigun.app shape in POST /@bluedeck/zhwp/arsession/shape.ts @returns { Promise<{ case_number: string }> } */
async function minigun_fullupload(revisions) {
const init = await (await fetch(`${REMOTE_HOST}/@bluedeck/zhwp/arsession/init`, {"method": "POST"})).json();
console.log(init);
const sessionid = init.sessionid;
const case_number = init.case_number;
for (const revs of arrgroup(revisions, 5)) {
console.log(await (await fetch(`${REMOTE_HOST}/@bluedeck/zhwp/arsession/${sessionid}/upload`, {
method: "POST",
body: revs.map(a => JSON.stringify(a)).join("\r\n"),
})).text());
}
const close = await (await fetch(`${REMOTE_HOST}/@bluedeck/zhwp/arsession/${sessionid}/close`, { method: "POST"})).json();
console.log(close);
return { case_number: case_number };
}
/**
* @param {string} pagename
* @param {Array} revisions
* @returns {Promise<string>}
*/
async function main_arproc_write(pagename, revisions) {
const index_page = "Wikipedia:已删除内容查询/查询/" + pagename;
const conforming_revisions = revisions.map(rev => ({
r: rev.revid.toString(),
p: rev.parentid?.toString() ?? "0",
pc: pagename,
rt: rev.timestamp,
s: rev.comment,
un: rev.user,
u: rev.userid.toString(),
c: rev["*"],
// r -- string -- rev id
// p -- string -- page id
// pc -- string -- page canon name (no hant-hans transformation)
// rt -- string -- rev timestamp
// s -- string -- edit summary
// un -- string -- user name
// u -- string -- user id
// c -- string -- content
}));
console.log(" ---------- Uploading to minigun ---------- ");
const { case_number } = await minigun_fullupload(conforming_revisions);
console.log(" ---------- Creating index page ---------- ");
const index_page_content_list = revisions.map(rev => `\n<tr><td> [${minigun_link(case_number, rev.revid)} '''查看存档'''] </td><td> ${rev.timestamp.split('T').join(' ').split('Z').join('')} </td><td> [[user talk:${rev.user}|]] </td><td> ${rev.size} </td><td> ${rev.revid} </td><td> ${replace_string_escape_wikitext(rev.comment)}</td></tr>`)
const final_rev = await asyncfetchedit(
index_page,
"页面[[:"+pagename+"]]共有"+revisions.length+"个已删除版本,存档如下:\n----\n<table style='white-space:nowrap'><tr><td></td><td>'''编辑时分'''</td><td>'''用户'''</td><td>'''页面大小'''</td><td>'''版本号'''</td><td>'''编辑摘要'''</td></tr>"+index_page_content_list.toReversed().join("")+"\n</table>\n----\n{"+"{subst:User:Bluedeck/infr/ar.thankyou.js}}",
"DRV lookup: [[:"+pagename+"]]",
await load_token(),
);
console.log("All done: ", final_rev);
return index_page;
}
}