Użytkownik:Expert3222/quickPatrol.js
Z Nondanych
Uwaga: aby zobaczyć zmiany po opublikowaniu, może zajść potrzeba wyczyszczenia pamięci podręcznej przeglądarki.
- Firefox / Safari: Przytrzymaj Shift podczas klikania Odśwież bieżącą stronę, lub naciśnij klawisze Ctrl+F5, lub Ctrl+R (⌘-R na komputerze Mac)
- Google Chrome: Naciśnij Ctrl-Shift-R (⌘-Shift-R na komputerze Mac)
- Internet Explorer / Edge: Przytrzymaj Ctrl, jednocześnie klikając Odśwież, lub naciśnij klawisze Ctrl+F5
- Opera: Naciśnij klawisze Ctrl+F5.
/*
* gadżet do szybkiego oznaczania wersji jako sprawdzonych na OZ, nowych stronach i widoku diffów
* autor: Expert3222
* drobne modyfikacje: Ostrzyciel
*/
// TODO: $(this) na $this (do zmiennej), lepsza wydajność będzie
var QuickPatrolLastClick = 0; //https://stackoverflow.com/questions/28609994/javascript-prevent-function-from-executing-multiple-times
var QuickPatrolDelay = 20; //syfiło w logach, rejestrując patrolowanie po kilka razy
var QuickPatrolToken = null;
var QuickPatrolDiffPageRevids = [];
var spinnerCode = "<div class='mw-spinner mw-spinner-small mw-spinner-inline' title='...'></div>";
//fix dla
//https://nonsa.pl/wiki/Plik:Patrolowe_czworaczki.jpg
var makePatrolLinksIsExecuting = false;
var makeDiffViewRevidsListIsExecuting = false;
var makeFilePatrolLinkCallCount = 0;
$(document).ready(function()
{
if (mw.config.get("wgCanonicalSpecialPageName") === "Recentchanges")
{
makePatrolLinks();
if (!!$('.mw-rcfilters-enabled').length) //wzięte od Polskacafe z gadżetu RollWithReason
{
setInterval(makePatrolLinks, 2000);
}
}
else if (mw.config.get("wgCanonicalSpecialPageName") == "Newpages")
{
makeNewpagesPatrolLinks();
}
else if (mw.util.getParamValue("diff") !== null)
{
var parse = function()
{
var oldid = mw.util.getParamValue("oldid", $("#mw-diff-otitle1 > strong > a").attr("href"));
//alert("oldid = " + oldid);
var curid = mw.util.getParamValue("oldid", $("#mw-diff-ntitle1 > strong > a").attr("href"));
//alert("curid = " + curid);
var title = mw.config.get("wgPageName").replace("_", " ");
//console.log(oldid, curid, title);
makeDiffViewRevidsList(oldid, curid, title);
};
parse();
setInterval(parse, 2000); //"przeglądaj historię interaktywnie" na górze
}
else if (mw.config.get("wgCanonicalSpecialPageName") == "MobileDiff")
{
//TODO
/*var oldid = mw.util.getParamValue("oldid", $("#mw-mf-diff-info a").attr("href"));
alert("oldid = " + oldid);
var urlArray = window.location.href.split("/");
var curid = urlArray[urlArray.length - 1];
alert("curid = " + curid);
var title = $("#mw-mf-diff-info a").text();
makeDiffViewRevidsList(oldid, curid, title);*/
}
});
function makePatrolLinks()
{
if (makePatrolLinksIsExecuting)
{
return;
}
makePatrolLinksIsExecuting = true;
//podstawowa logika: mamy liczbę zaplanowanych wywołań AJAX i liczbę zakończonych. Chcemy zaznaczyć, że funkcja skończyła się wykonywać, gdy obie wartości będą równe.
//ale czysto teoretycznie może dojść do sytuacji, w której liczba zaplanowanych zapytań nie będzie tą finalną, a obie będą równe.
//dlatego sprawdzamy tylko wtedy, gdy kontrola doszła do końca funkcji (czyli wiemy finalnie, ile AJAX-ów będzie)
var AJAXCallsCompleted = 0;
var reachedEndOfFunction = false;
function handleEndOfAJAXCall()
{
++AJAXCallsCompleted;
if (AJAXCallsCompleted == makeFilePatrolLinkCallCount && reachedEndOfFunction)
{
makePatrolLinksIsExecuting = false;
makeFilePatrolLinkCallCount = 0;
}
}
//pojedyncze zmiany i pojedyncze przesłania pliku
$("table.mw-changeslist-reviewstatus-unpatrolled").each(function()
{
if ($(this).find(".patrolButton").length === 0 && $(this).find(".patrolButtonClicked").length === 0) //jeśli nie ma buttona i nie został wcześniej użyty
{
if (typeof $(this).attr("data-mw-logaction") == "undefined") //zmiana
{
$(this).find(".mw-changeslist-links:not(.mw-usertoollinks)").append("<span class='patrolButton' title='Oznacz tę zmianę jako sprawdzoną' data-diff='" + $(this).attr("data-mw-revid") + "'><a>patrol</a></span>");
}
else //przesłanie pliku
{
var extraAttributes =
{
"data-mw-logid": $(this).attr("data-mw-logid"),
"data-mw-ts": $(this).attr("data-mw-ts")
};
var overwritten = ($(this).attr("data-mw-logaction") == "upload/upload") ? false : true;
makeFilePatrolLink($(this), overwritten, extraAttributes).always(handleEndOfAJAXCall);
}
}
});
//wielokrotne zmiany, które można rozwijać i zwijać + przesłane pliki, też wielokrotne
$("tr.mw-enhanced-rc.mw-changeslist-reviewstatus-unpatrolled").each(function()
{
if ($(this).find(".patrolButton").length === 0 && $(this).find(".patrolButtonClicked").length === 0)
{
var found = $(this).find(".mw-changeslist-diff");
if (found.length > 0) //jest link w "poprz", czyli strona nie została utworzona w tej edycji
{
$(found).after(" • <span class='patrolButton' title='Oznacz tę zmianę jako sprawdzoną' data-diff='" + $(this).attr("data-mw-revid") + "'><a>patrol</a></span>");
}
else if (typeof $(this).attr("data-mw-logaction") == "undefined") //strony stworzone w tej edycji
{
$(this).html($(this).html().replace("• poprz.", "• poprz. • <span class='patrolButton' title='Oznacz tę zmianę jako sprawdzoną' data-diff='" + $(this).attr("data-mw-revid") + "'><a>patrol</a></span>"));
}
else if ($(this).attr("data-mw-logaction") == "upload/upload") //przesłane pliki
{
var extraAttributes =
{
"data-mw-logid": $(this).attr("data-mw-logid"),
"data-mw-ts": $(this).attr("data-mw-ts")
};
makeFilePatrolLink($(this), false, extraAttributes).always(handleEndOfAJAXCall);
}
else if ($(this).attr("data-mw-logaction") == "upload/overwrite") //nadpisane pliki
{
var extraAttributes =
{
"data-mw-logid": $(this).attr("data-mw-logid"),
"data-mw-ts": $(this).attr("data-mw-ts")
};
makeFilePatrolLink($(this), true, extraAttributes).always(handleEndOfAJAXCall);
}
}
});
//link do patrolowania wszystkich zmian danej strony
$("table.mw-collapsible > tbody").each(function()
{
var lines = $(this).find("tr");
var firstLine = $(lines).first();
if (lines.length >= 2 && $(firstLine).hasClass("mw-changeslist-reviewstatus-unpatrolled") &&
$(firstLine).find(".multiplePatrolButton").length === 0 && $(firstLine).find(".multiplePatrolButtonClicked").length === 0)
{
$(firstLine).find("span.mw-changeslist-links > span:nth-child(2)").after("<span class='multiplePatrolButton' title='Oznacz zmiany tej strony jako sprawdzone'><a>patroluj tę stronę</a></span>");
$(firstLine).find(".multiplePatrolButton").on("click", function()
{
patrolMultipleChanges($(lines).parent());
});
}
});
$(".patrolButton").on("click", function()
{
patrolChange($(this).attr("data-diff"), false, false);
});
if (makeFilePatrolLinkCallCount === 0 || AJAXCallsCompleted == makeFilePatrolLinkCallCount)
{
makePatrolLinksIsExecuting = false;
makeFilePatrolLinkCallCount = 0;
}
reachedEndOfFunction = true;
}
function makeFilePatrolLink(elem, overwritten, extraAttributes)
{
//console.log(elem);
++makeFilePatrolLinkCallCount;
/*console.log(makeFilePatrolLinkCallCount);
console.dir(elem[0]);*/
var api = new mw.Api(),
fileName = $(elem).find(".mw-changeslist-log-entry > a:not(.mw-userlink)").attr("title"),
deferred = $.Deferred();
if (fileName.indexOf(" (strona nie istnieje)") == -1) //jeśli plik istnieje (w przeciwnym przypadku przycisk patrolowania jest zbędny)
{
if (!overwritten)
{
//bierzemy sobie numer pierwszej wersji pliku, który jest potrzebny do patrolowania
api.post(
{
action: 'query',
format: 'json',
formatversion: '2',
prop: 'revisions',
titles: fileName,
rvprop: 'ids',
rvlimit: '1',
rvdir: 'newer'
}).done(function(data)
{
var oldid = data.query.pages[0].revisions[0].revid;
$(elem).find(".mw-changeslist-log-entry > a:not(.mw-userlink)").after(" (<span class='patrolButton' title='Oznacz tę zmianę jako sprawdzoną' data-diff='" + oldid + "'><a>patrol</a></span>)");
var $button = $(elem).find(".patrolButton");
$button.on("click", function()
{
patrolChange(oldid, false, false);
});
$.each(extraAttributes, function(name, value)
{
$button.attr(name, value);
});
deferred.resolve();
}).fail(function(error)
{
console.log(error);
deferred.reject();
});
}
else
{
//bierzemy numer konkretnej wersji pliku (takie obejście potrzebne, bo tylko w tym wypadku nie ma atrybutu data-mw-revid)
var timestamp = $(elem).attr("data-mw-ts");
api.post(
{
action: 'query',
format: 'json',
formatversion: '2',
prop: 'revisions',
titles: fileName,
rvprop: 'ids',
rvlimit: '1',
rvstart: timestamp,
rvend: timestamp
}).done(function(data)
{
var oldid = data.query.pages[0].revisions[0].revid;
$(elem).find("td>a:nth-child(5)").after(" (<span class='patrolButton' data-diff='" + oldid + "'><a>patrol</a></span>)");
$(elem).find(".patrolButton").on("click", function()
{
patrolChange(oldid, false, false);
});
deferred.resolve();
}).fail(function(error)
{
console.log(error);
deferred.reject();
});
}
}
else
{
deferred.resolve();
}
return deferred.promise();
}
function makeNewpagesPatrolLinks()
{
$("li.not-patrolled").each(function()
{
if (typeof $(this).find(".mw-newpages-oldtitle") == "undefined")
{
var oldid = $(this).attr("data-mw-revid");
$(this).find("span.mw-newpages-history a").after(" • <span class='patrolButton' title='Oznacz tę stronę jako sprawdzoną' data-diff='" + oldid + "'><a>patrol</a></span>");
}
else
{
var api = new mw.Api(),
elem = $(this),
pageName = $(this).find(".mw-newpages-pagename").attr("title");
api.post(
{
action: 'query',
format: 'json',
formatversion: '2',
prop: 'revisions',
titles: pageName,
rvprop: 'ids',
rvlimit: '1',
rvdir: 'newer'
}).done(function(data)
{
var oldid = data.query.pages[0].revisions[0].revid;
$(elem).find("span.mw-newpages-history a").after(" • <span class='patrolButton' title='Oznacz tę stronę jako sprawdzoną' data-diff='" + oldid + "'><a>patrol</a></span>");
$(elem).find(".patrolButton").on("click", function()
{
patrolChange(oldid, false, false);
});
}).fail(function(error)
{
console.log(error);
});
}
});
$(".patrolButton").on("click", function()
{
patrolChange($(this).attr("data-diff"), false, false);
});
}
function patrolChange(diff, isDiffPagePatrol, tokenAlreadyReset)
{
if (QuickPatrolLastClick >= (Date.now() - QuickPatrolDelay))
return;
QuickPatrolLastClick = Date.now();
if (diff === null || diff === "" || typeof diff == "undefined")
{
return $.when(); //resolved promise
}
var api = new mw.Api(),
$button = undefined, //button to nasz przycisk do patrolowania
deferred = $.Deferred();
if (!isDiffPagePatrol)
{
$button = $(".patrolButton[data-diff='" + diff + "']");
$button.off("click").find("a").replaceWith(spinnerCode);
}
api.post(
{
action: 'patrol',
format: 'json',
revid: diff,
token: mw.user.tokens.get("patrolToken")
}).done(function(data)
{
if (!isDiffPagePatrol)
{
if (typeof $button.attr("data-mw-ts") == "undefined") //patrol zwykłej strony
{
$("table[data-mw-revid='" + diff + "'] abbr.unpatrolled").replaceWith(' ');
$("tr[data-mw-revid='" + diff + "'] abbr.unpatrolled").replaceWith(' ');
}
else //patrol pliku
{
var timestamp = $button.attr("data-mw-ts"),
logid = $button.attr("data-mw-logid");
$("table[data-mw-ts=" + timestamp + "] tr[data-mw-logid=" + logid + "] abbr.unpatrolled").replaceWith(' ');
}
var $anchor = $button.parent(); //koniecznie, bo zaraz $button nie bedzie mialo wartosci
$button.replaceWith("<span><img src='https://nonsa.pl/images/2/26/Za.svg.png' width='15px' height='15px' /> <span style='color: green;' class='patrolButtonClicked'>zrobione</span><span>");
processGroupMarksAndButtons($anchor);
}
deferred.resolve();
}).fail(function(error)
{
if (!tokenAlreadyReset)
{
console.log("TOKEN PATROLOWANIA NIEPRAWIDŁOWY - DRUGA PRÓBA");
api.post
({
format: "json",
formatversion: "2",
action: "query",
meta: "tokens",
type: "patrol"
}).done(function(data)
{
mw.user.tokens.set("patrolToken", data.query.tokens.patroltoken);
patrolChange(diff, isDiffPagePatrol, true)
.done(function()
{
deferred.resolve();
console.log("NOWY TOKEN PRAWIDŁOWY");
}).fail(function()
{
deferred.reject();
console.log("NOWY TOKEN NIEPRAWIDŁOWY");
});
});
}
else // w przypadku pierwszego faila to zostanie wykonane przez funkcję wywołaną rekursywnie
{
if (!isDiffPagePatrol)
{
$button.replaceWith("<img src='https://nonsa.pl/images/a/a8/Przeciw.svg.png' width='15px' height='15px' /> <span style='color: red;' class='patrolButtonClicked'>błąd</span>");
}
console.log(error);
deferred.reject();
}
});
return deferred.promise();
}
function patrolMultipleChanges(tbody)
{
var deferred = $.Deferred(),
failureCount = 0,
successCount = 0,
multiplePatrolButton = tbody.find(".multiplePatrolButton"),
buttons = $(tbody).find(".patrolButton"),
buttonsCount = buttons.length;
multiplePatrolButton.off("click").find("a").replaceWith(spinnerCode);
buttons.each(function()
{
QuickPatrolLastClick = 0;
patrolChange($(this).attr("data-diff"), false, false)
.done(function()
{
++successCount;
}).fail(function()
{
++failureCount;
}).always(function()
{
if (successCount == buttonsCount) //wszystkie wywołania AJAX do patrolowania zakończyły się pomyślnie
{
deferred.resolve(successCount, failureCount);
multiplePatrolButton.replaceWith("<span><img src='https://nonsa.pl/images/2/26/Za.svg.png' width='15px' height='15px' /> <span style='color: green;' class='multiplePatrolButtonClicked'>zrobione</span></span>");
tbody.find("tr:first-child abbr.unpatrolled").replaceWith(" ");
}
else if (successCount + failureCount == buttonsCount) //wszystkie zakończyły się, niekoniecznie pomyślnie
{
deferred.reject(successCount, failureCount);
multiplePatrolButton.replaceWith("<img src='https://nonsa.pl/images/a/a8/Przeciw.svg.png' width='15px' height='15px' /> <span style='color: red;' class='multiplePatrolButtonClicked'>błąd</span>");
}
});
});
if (buttonsCount == 0)
{
multiplePatrolButton.replaceWith("<span><img src='https://nonsa.pl/images/2/26/Za.svg.png' width='15px' height='15px' /> <span style='color: green;' class='multiplePatrolButtonClicked'>zrobione</span></span>");
tbody.find("tr:first-child abbr.unpatrolled").replaceWith(" ");
}
return deferred.promise();
}
function makeDiffViewRevidsList(oldid, curid, pagetitle)
{
if ($(".diffPagePatrolButton").length || $(".diffPagePatrolButtonClicked").length || makeDiffViewRevidsListIsExecuting)
{
return;
}
makeDiffViewRevidsListIsExecuting = true;
var api = new mw.Api(),
timestampQueryData = function(id)
{
var ret =
{
format: "json",
formatversion: 2,
action: "query",
prop: "revisions",
rvprop: "timestamp",
rvstartid: id,
rvendid: id,
titles: pagetitle
};
return ret;
};
var leftEditIsPageCreation = ($("#differences-prevlink").length == 0); // czy jest link "przejdź do poprzedniej edycji"
api.post
(
timestampQueryData(oldid)
).done(function(data)
{
//debugger;
var firstTimestamp = data.query.pages[0].revisions[0].timestamp;
//debugger;
//żeby nie oznaczało jako sprawdzonej pierwszej zmiany (po lewej)
if (!leftEditIsPageCreation) //ale tylko jeśli była edycja przedtem
{
var date = new Date(firstTimestamp);
date.setSeconds(date.getSeconds() + 1);
function pad2withzeros(number)
{
return String(number).padStart(2, "0");
}
firstTimestamp = date.getUTCFullYear() + "-" + pad2withzeros(date.getUTCMonth() + 1) + "-" + pad2withzeros(date.getUTCDate()) + "T" + pad2withzeros(date.getUTCHours()) + ":" + pad2withzeros(date.getUTCMinutes()) + ":" + pad2withzeros(date.getUTCSeconds()) + "Z";
}
api.post
(
timestampQueryData(curid)
).done(function(data)
{
//debugger;
var secondTimestamp = data.query.pages[0].revisions[0].timestamp;
api.post(
{
format: "json",
formatversion: 2,
action: "query",
list: "recentchanges",
rcstart: firstTimestamp,
rcend: secondTimestamp,
rcdir: "newer",
rctitle: pagetitle,
rcshow: "!patrolled",
rcprop: "ids"
}).done(function(data)
{
//debugger;
var length = data.query.recentchanges.length;
for (var i = 0; i < length; ++i)
{
QuickPatrolDiffPageRevids.push(data.query.recentchanges[i].revid);
}
if (length > 0)
{
makeDiffPagePatrolButton();
}
makeDiffViewRevidsListIsExecuting = false;
}).fail(function(error)
{
makeDiffViewRevidsListIsExecuting = false;
});
}).fail(function(error)
{
makeDiffViewRevidsListIsExecuting = false;
});
}).fail(function(error)
{
makeDiffViewRevidsListIsExecuting = false;
});
}
function makeDiffPagePatrolButton()
{
var patrolButtonCode = "<span class='diffPagePatrolButton'>[<a title='oznacz wszystkie edycje widoczne w porównaniu jako sprawdzone'>oznacz wszystkie edycje jako sprawdzone</a>]</span>";
if (mw.config.get("skin") != "minerva" && mw.config.get("wgCanonicalSpecialPageName") != "MobileDiff")
{
var patrolLink = $("#mw-diff-ntitle4 .patrollink");
if (patrolLink.length > 0)
{
patrolLink.replaceWith(patrolButtonCode);
}
else
{
$("#mw-diff-ntitle4").append(" " + patrolButtonCode);
}
}
else
{
//debugger;
$(".patrollink").append(" • " + patrolButtonCode.replace(/(\[|\])/g, "")); //bez kwadratowych nawiasów
}
$(".diffPagePatrolButton a").click(function()
{
patrolMultipleChangesDiffPage();
});
}
function patrolMultipleChangesDiffPage()
{
var deferred = $.Deferred(),
failureCount = 0,
successCount = 0,
length = QuickPatrolDiffPageRevids.length,
button = $(".diffPagePatrolButton");
//debugger;
button.off("click").find("a").replaceWith(spinnerCode);
//debugger;
QuickPatrolDiffPageRevids.forEach(function(oldid)
{
QuickPatrolLastClick = 0;
patrolChange(oldid, true, false)
.done(function()
{
++successCount;
}).fail(function()
{
++failureCount;
}).always(function()
{
if (successCount == length)
{
deferred.resolve(successCount, failureCount);
//debugger;
button.replaceWith("<img src='https://nonsa.pl/images/2/26/Za.svg.png' width='15px' height='15px' /> <span style='color: green;' class='diffPagePatrolButtonClicked'>zrobione</span>");
//debugger;
}
else if (successCount + failureCount == length)
{
deferred.reject(successCount, failureCount);
button.replaceWith("<img src='https://nonsa.pl/images/a/a8/Przeciw.svg.png' width='15px' height='15px' /> <span style='color: red;' class='diffPagePatrolButtonClicked'>błąd</span>");
}
});
//debugger;
});
//debugger;
return deferred.promise();
}
function processGroupMarksAndButtons($anchor) //usuwa grupowy wykrzyknik i przycisk patrolowania, jak zajdzie potrzeba
{
var $parent = $anchor;
while ($parent.prop("tagName") != "TABLE" && $parent.prop("tagName") != "BODY")
{
$parent = $parent.parent();
}
//wszystkie rozwijalne zmiany/pliki spatrolowane, drugi warunek po to,
//zeby nie ignorowalo sytuacji, gdy zmiany nie udalo sie spatrolowac
if ($parent.find(".patrolButton").length == 0 && $parent.find("abbr.unpatrolled").length == 1)
{
$parent.find("abbr.unpatrolled").replaceWith(" ");
$parent.find(".multiplePatrolButton").replaceWith("<span><img src='https://nonsa.pl/images/2/26/Za.svg.png' width='15px' height='15px' /> <span style='color: green;' class='multiplePatrolButtonClicked'>zrobione</span></span>");
}
}