משתמש:מוטי בוט/עדכון קטגוריה.js
מראה
לתשומת ליבך: לאחר הפרסום, ייתכן שיהיה צורך לנקות את זיכרון המטמון (cache) של הדפדפן כדי להבחין בשינויים.
- פיירפוקס / ספארי: להחזיק את המקש Shift בעת לחיצה על טעינה מחדש (Reload) או ללחוץ על צירוף המקשים Ctrl-F5 או Ctrl-R (במחשב מק: ⌘-R).
- גוגל כרום: ללחוץ על צירוף המקשים Ctrl-Shift-R (במחשב מק: ⌘-Shift-R).
- אדג': להחזיק את המקש Ctrl בעת לחיצה על רענן (Refresh) או ללחוץ על צירוף המקשים Ctrl-F5.
//הקוד הראשוני נכתב ע"י משתמש גאון הירדן שופץ ושוכתב על ידי
/**
* Creates a button that, when clicked, prompts the user to confirm whether they want to update a category.
* If the user confirms, the `upAll` function is called.
*/
mw.loader
.using([
"mediawiki.api",
"mediawiki.util",
"mediawiki.ForeignApi",
"ext.gadget.mw-import",
])
.done(function () {
if (mw.config.get("wgNamespaceNumber") !== 14) {
return;
}
const api = new mw.Api();
const wiki = new mw.ForeignApi(mw.user.options.get("userjs-import-source") === "direct" ? "https://he.wikipedia.org/w/api.php" : "/import/get_wik1i.php", {
anonymous: true,
});
const Import = new mw.import(mw.user.options.get("userjs-import-source") === "direct" ? "https://he.wikipedia.org/w/api.php" : "https://import.hamichlol.org.il/");
let isPaused = false;
let isRunning = false;
let currentState = null;
function createButton() {
const button = mw.util.addPortletLink(
"p-views",
"#",
"עדכון כל הקטגוריה",
"updateCategory",
null,
null,
"#ca-history"
);
$(button).click(() => {
console.log("Clicked the button! isPaused: " + isPaused);
if (!isRunning) {
console.log("Starting new update!");
isRunning = true;
updateAllPags();
$(button).find("a").text("השהה עדכון");
} else {
console.log("Toggling update state!");
isPaused = !isPaused;
if (!isPaused) updateAllPags(currentState);
$(button)
.find("a")
.text(isPaused ? "המשך עדכון" : "השהה עדכון");
}
});
}
async function updateAllPags(state = null) {
if (!state) {
const localMap = await memberList("local");
const wikiMap = await memberList("wikipedia");
state = {
localMap,
wikiMap,
localTitles: Object.keys(localMap),
index: 0,
stage: "localMap",
};
}
let { localMap, wikiMap, localTitles, index, stage } = state;
if (stage === "localMap") {
while (index < localTitles.length) {
if (isPaused) {
currentState = { localMap, wikiMap, localTitles, index, stage };
return;
}
const title = localTitles[index];
index++;
const isWiki = wikiMap[title];
const isUpdate = compareTimestamps(
localMap[title]?.revisions[0]?.timestamp,
wikiMap[title]?.revisions[0]?.timestamp || 0
);
const lastRevision = localMap[title].revisions[0];
const filter =
!/יבוא|עי?דכון|יובאה/.test(lastRevision.comment) ||
/תמונה|תוכן/.test(lastRevision.comment) ||
lastRevision.comment.includes("nowiki") ||
lastRevision.tags.some(
(tag) => tag === "הסרת תמונה" || tag === "הסרת תוכן"
);
if (isWiki && !isUpdate) {
delete localMap[title];
delete wikiMap[title];
continue;
}
if (filter) {
console.warn(`${title} עבר עריכה מקומית!`, lastRevision);
delete localMap[title];
if (isWiki) delete wikiMap[title];
continue;
}
try {
const { text, summary } = await Import.importWikitext({
page: title,
exist: true,
});
await editTemplate(title, text, summary);
} catch {}
delete localMap[title];
if (isWiki) delete wikiMap[title];
}
stage = "wikiMap";
index = 0;
}
console.log("localMapLength", Object.keys(localMap).length);
console.log("wikiMapLength", Object.keys(wikiMap).length);
if (stage === "wikiMap") {
for (const member in wikiMap) {
if (isPaused) {
currentState = { localMap, wikiMap, index: 0, stage };
return;
}
mw.notify(`מייבא ${member}...`);
try {
const shouldUpdate = await confirmUpdate(member);
if (shouldUpdate === false) continue;
const { text, summary } = await Import.importWikitext({
page: member,
exist: shouldUpdate,
});
await editTemplate(member, text, summary);
} catch (error) {
console.error(error);
}
}
}
// Reset when finished
currentState = null;
isPaused = false;
$("#updateCategory").find("a").text("עדכון חוזר");
}
/**
* Retrieves a list of members from a specified category on either the local wiki or an external wiki.
* @param {string} targetApi - A string indicating the API to use. It can be either "local" for the local wiki or "wikipedia" for an external wiki. The default value is "w".
* @param {Array} members - An array to store the fetched members. The default value is an empty array.
* @param {string} gcmcontinue - A string representing the continue parameter for pagination. The default value is `null`.
* @returns {Promise<Array>} - An array of member objects representing the members of the specified category.
*/
async function memberList(targetApi) {
const category = mw.config.get("wgPageName");
const members = {};
let gcmcontinue = null;
const parameters = {
prop: "revisions",
generator: "categorymembers",
utf8: 1,
rvprop: "timestamp",
gcmtitle: category,
gcmnamespace: "10",
gcmlimit: "max",
};
if (targetApi === "local") {
parameters.rvprop = "timestamp|comment|tags";
}
const apiGet = targetApi === "wikipedia" ? wiki : api;
while (true) {
if (gcmcontinue) {
parameters.gcmcontinue = gcmcontinue;
}
try {
const response = await apiGet.get(parameters);
Object.keys(response.query.pages).forEach((id) => {
members[response.query.pages[id].title] = response.query.pages[id];
});
console.log(response);
console.log(Object.keys(members).length);
if (response.continue) {
gcmcontinue = response.continue.gcmcontinue;
} else {
break;
}
} catch (error) {
console.error("Error fetching members:", error);
break;
}
}
return members;
}
function compareTimestamps(localtimestamp, wikitimestamp) {
const localDate = Date.parse(localtimestamp);
const wikiDate = Date.parse(wikitimestamp);
// Rest of the code
return localDate < wikiDate;
}
/**
* Makes an API call to edit a wiki page with the provided title, wikitext, and summary.
* @param {string} title - The title of the wiki page to be edited.
* @param {string} wikitext - The content of the wiki page to be edited.
* @param {string} summary - The summary of the edit.
* @returns {Promise<void>}
*/
async function editTemplate(title, wikitext, summary) {
try {
const { edit } = await api.postWithEditToken({
action: "edit",
format: "json",
bot: true,
title,
text: wikitext,
summary,
tags: "auto-update",
});
if (edit) {
console.log(title, edit);
if (edit?.new === "") mw.notify(`תבנית ${title} יובאה`);
}
} catch (error) {
console.error(`Error editing ${title}:`, error);
}
}
async function confirmUpdate(member) {
const windowManager = new OO.ui.WindowManager();
$("body").append(windowManager.$element);
const messageDialog = new OO.ui.MessageDialog();
windowManager.addWindows([messageDialog]);
const linkElement = $("<a>", {
href: `/${member}`,
text: member,
});
// בדיקת קיום הדף
let pageExists = false;
try {
const result = await api.get({
titles: member,
formatversion: 2,
});
pageExists = !result.query.pages[0].missing ;
linkElement.addClass(!pageExists ? "new" : "");
} catch (error) {
console.error("Error checking page existence:", error);
}
const message = $("<p>").append("האם ברצונך לעדכן ", linkElement);
const config = {
message: message,
actions: [
{ action: "accept", label: "כן", flags: ["primary", "progressive"] },
{ action: "reject", label: "לא", flags: "safe" },
],
};
const result = await windowManager.openWindow(messageDialog, config)
.closed;
windowManager.$element.remove(); // ניקוי ה-DOM לאחר השימוש
if (!result || result.action === "reject") {
return false;
} else if (result.action === "accept") {
return !pageExists ? 0 : 1;
}
}
mw.user.getRights((r) => {
if (r.includes("bot")) createButton();
});
});