Jumat, 16 Oktober 2026
23:32 WIB
TERKINI
Pesawaran Lampung Dorong Rantai Pasok Hijau Kakao, Kopi, Lada ke Pasar Global Pesawaran Pengalihan Status Guru PPPK ke Penuh Waktu: DPRD Pesawaran Soroti Isu Penempatan Lampung Timur Gotong Royong Fantastis: Warga Bandar Agung Himpun Rp15 Miliar untuk Jalan Desa Bandar Lampung JNE Lampung Sukses Ubah Komplain Milea Cutting Jadi Kemitraan Strategis Bandar Lampung Jadwal Padat Pemprov Lampung 16 Oktober 2026: Pisah Sambut Kapolda dan Rapat Strategis Bandar Lampung Lampung Waspada: BMKG Deteksi 212 Titik Panas di Sepuluh Kabupaten Bandar Lampung Masyarakat Lampung Titip Harapan Besar untuk Kapolda Baru: Berantas Narkoba dan Begal Regional Gubernur Herman Deru Minta Polisi Usut Tuntas Pengeroyokan Jurnalis di Palembang Lampung Selatan Bau Menyengat dan Lalat Ungkap Kematian Pria di Natar, Diduga Sakit Kronis Hiburan Daftar Film Paling Dipuji di IMDb 2026: Dari Epik Kolosal hingga Aksi Pahlawan Super Pesawaran Lampung Dorong Rantai Pasok Hijau Kakao, Kopi, Lada ke Pasar Global Pesawaran Pengalihan Status Guru PPPK ke Penuh Waktu: DPRD Pesawaran Soroti Isu Penempatan Lampung Timur Gotong Royong Fantastis: Warga Bandar Agung Himpun Rp15 Miliar untuk Jalan Desa Bandar Lampung JNE Lampung Sukses Ubah Komplain Milea Cutting Jadi Kemitraan Strategis Bandar Lampung Jadwal Padat Pemprov Lampung 16 Oktober 2026: Pisah Sambut Kapolda dan Rapat Strategis Bandar Lampung Lampung Waspada: BMKG Deteksi 212 Titik Panas di Sepuluh Kabupaten Bandar Lampung Masyarakat Lampung Titip Harapan Besar untuk Kapolda Baru: Berantas Narkoba dan Begal Regional Gubernur Herman Deru Minta Polisi Usut Tuntas Pengeroyokan Jurnalis di Palembang Lampung Selatan Bau Menyengat dan Lalat Ungkap Kematian Pria di Natar, Diduga Sakit Kronis Hiburan Daftar Film Paling Dipuji di IMDb 2026: Dari Epik Kolosal hingga Aksi Pahlawan Super

MediaWiki:Gadget-FoxTools-Rollback.js

Bagikan:
/**
 * [FOXTOOLS — PATROLLERS HELPER SCRIPT]
 * 
 * •==============================================•
 * > Pencipta: Janorovic Volkov
 * > Pengembang: Janorovic Volkov
 * > Tipe: JavaScript (Module)
 * 
 * Lihat [[WP:FT]] untuk informasi selengkapnya
 * tentang skrip ini
 * •==============================================•
 */
// <nowiki>
mw.loader.load('mediawiki.ui.button');
(function(){
constFT=window.FoxTools||{};
constapi=newmw.Api();
functionnotiOK(msg){mw.notify?mw.notify(msg,{type:'success'}):alert(msg);}
functionnotiWARN(msg){mw.notify?mw.notify(msg,{type:'warn'}):alert(msg);}
functionaskComment(){
constc=prompt("🦊 FoxTools — Rollback\n\nKlik batal jika ingin membatalkan pengembalian.\nMasukkan komentar (opsional):","");
if(c===null)returnnull;
if(c.trim()==="")return"";
return`: ${c.trim()}`;
}
asyncfunctionfoxUndoRollback(page,undoRev,undoAfterRev,summary){
constparams={
action:'edit',
title:page,
undo:undoRev,
summary,
minor:true,
tags:'FoxTools',
redirect:false
};
if(undoAfterRev)params.undoafter=undoAfterRev;
returnawaitapi.postWithToken('csrf',params);
}
functionfindUndoAfter(revs,targetRevId,targetUser){
constidx=revs.findIndex(r=>r.revid===targetRevId);
if(idx===-1)returnnull;
for(leti=idx+1;i<revs.length;i++){
if(revs[i].user!==targetUser)returnrevs[i].revid;
}
returnnull;
}
asyncfunctionrollbackUser(page,targetRevId,user,isANB=false){
constrevs=awaitfetchRevisions(page,'max');
constidx=revs.findIndex(r=>r.revid===targetRevId);
if(idx===-1)return;
letundoRev=targetRevId;
letundoAfter=null;
for(leti=idx+1;i<revs.length;i++){
if(revs[i].user!==user){
undoAfter=revs[i].revid;
break;
}
}
leteditCount=0;
for(leti=idx;i<revs.length;i++){
if(revs[i].user===user)editCount++;
elsebreak;
}
constcomment=askComment();
if(comment===null)return;
consttargetUserRev=undoAfter?awaitgetUserOfRevision(undoAfter):null;
constsummary=isANB
?summaryANBToTarget(page,user,editCount,targetUserRev,comment)
:summaryNormalToTarget(page,user,editCount,targetUserRev,comment);
awaitfoxUndoRollback(page,undoRev,undoAfter,summary);
notiOK(`🟢 Pengembalian revisi berhasil: ${user} (${editCount})`);
location.reload();
}
asyncfunctiongetUserOfRevision(revid){
constres=awaitapi.get({
action:'query',
prop:'revisions',
revids:revid,
rvprop:'user',
formatversion:2
});
constpage=res.query.pages[0];
constrev=page.revisions&&page.revisions[0];
returnrev?rev.user:null;
}
asyncfunctiongetLatestRevId(page){
constres=awaitapi.get({
action:'query',
prop:'revisions',
titles:page,
rvlimit:1,
rvprop:'ids',
formatversion:2
});
constpageObj=res.query.pages&&res.query.pages[0];
returnpageObj&&pageObj.revisions&&pageObj.revisions[0]&&pageObj.revisions[0].revid;
}
asyncfunctionfetchRevisions(page,limit='max'){
constres=awaitapi.get({
action:'query',
prop:'revisions',
titles:page,
rvlimit:limit,
rvprop:'ids|user|timestamp',
formatversion:2
});
constrevs=(res.query.pages&&res.query.pages[0]&&res.query.pages[0].revisions)||[];
returnrevs;
}
functionfindLastGoodRevIdFromRevisions(revs,targetRevId,targetUser){
letidx=revs.findIndex(r=>r.revid===targetRevId);
if(idx===-1)returnnull;
for(leti=idx+1;i<revs.length;i++){
if(revs[i].user!==targetUser){
returnrevs[i].revid;
}
}
returnnull;
}
functioncountConsecutiveEdits(revs,targetRevId,targetUser){
letidx=revs.findIndex(r=>r.revid===targetRevId);
if(idx===-1)return1;
letcount=0;
for(leti=idx;i<revs.length;i++){
if(revs[i].user===targetUser)count++;
elsebreak;
}
returnMath.max(1,count);
}
functionsummaryNormalToTarget(page,sourceUser,count,targetUser,comment){
if(count&&count>1){
return`Mengembalikan ${count} suntingan oleh [[Istimewa:Kontribusi/${sourceUser}|${sourceUser}]] ([[User talk:${sourceUser}|bicara]]) ke revisi terakhir oleh [[Istimewa:Kontribusi/${targetUser}|${targetUser}]]${comment} (${FT.ads})`;
}
return`Mengembalikan suntingan oleh [[Istimewa:Kontribusi/${sourceUser}|${sourceUser}]] ([[User talk:${sourceUser}|bicara]]) ke revisi terakhir oleh [[Istimewa:Kontribusi/${targetUser}|${targetUser}]]${comment} (${FT.ads})`;
}
functionsummaryANBToTarget(page,sourceUser,count,targetUser,comment){
if(count&&count>1){
return`Membatalkan ${count} [[WP:ANB|suntingan berniat baik]] oleh [[Istimewa:Kontribusi/${sourceUser}|${sourceUser}]] ([[User talk:${sourceUser}|bicara]]) ke revisi terakhir oleh [[Istimewa:Kontribusi/${targetUser}|${targetUser}]]${comment} (${FT.ads})`;
}
return`Membatalkan [[WP:ANB|suntingan berniat baik]] oleh [[Istimewa:Kontribusi/${sourceUser}|${sourceUser}]] ([[User talk:${sourceUser}|bicara]]) ke revisi terakhir oleh [[Istimewa:Kontribusi/${targetUser}|${targetUser}]]${comment} (${FT.ads})`;
}
functionsummaryRestoreToTarget(page,revId,targetUser,comment){
return`Memulihkan ke revisi [[Istimewa:Diff/${revId}|${revId}]] oleh [[Istimewa:Kontribusi/${targetUser}|${targetUser}]]${comment} (${FT.ads})`;
}
functionmkButton(text,classes='',title=''){
constbtn=document.createElement('button');
btn.className='mw-ui-button '+classes;
btn.textContent=text;
if(title)btn.title=title;
returnbtn;
}
functionattachButtonsToListItem($li,page,revid,user){
if($li.find('.foxtools-rollback-panel').length)return;
constpanel=document.createElement('span');
panel.className='foxtools-rollback-panel';
panel.style.marginLeft='8px';
panel.style.display='inline-flex';
panel.style.gap='6px';
constbtnANB=mkButton('Kembalikan (ANB)','mw-ui-button mw-ui-progressive');
constbtnNormal=mkButton('Kembalikan','mw-ui-button mw-ui-destructive');
btnANB.onclick=async()=>{
constuser=awaitgetUserOfRevision(revid);
awaitrollbackUser(page,revid,user,true);
};
btnNormal.onclick=async()=>{
constuser=awaitgetUserOfRevision(revid);
awaitrollbackUser(page,revid,user,false);
};
panel.appendChild(btnANB);
panel.appendChild(btnNormal);
const$tag=$li.find('.mw-tag-markers').first();
if($tag.length){
$tag.before(panel);
}else{
$li.append(panel);
}
}
functionattachHistoryButtons($row,page,revid,user){
if($row.find('.foxtools-rollback-panel-hist').length)return;
constpanel=document.createElement('span');
panel.className='foxtools-rollback-panel-hist';
panel.style.marginLeft='8px';
panel.style.display='inline-flex';
panel.style.gap='6px';
constbtnANB=mkButton('Kembalikan (ANB)','mw-ui-button mw-ui-progressive');
constbtnNormal=mkButton('Kembalikan','mw-ui-button mw-ui-destructive');
btnANB.onclick=async(e)=>{
e.preventDefault();
e.stopPropagation();
constuser=awaitgetUserOfRevision(revid);
awaitrollbackUser(page,revid,user,true);
};
btnNormal.onclick=async(e)=>{
e.preventDefault();
e.stopPropagation();
constuser=awaitgetUserOfRevision(revid);
awaitrollbackUser(page,revid,user,false);
};
panel.appendChild(btnANB);
panel.appendChild(btnNormal);
const$tag=$row.find('.mw-tag-markers').first();
if($tag.length){
$tag.before(panel);
}else{
$row.append(panel);
}
}
asyncfunctionaddFoxRollbackButtons(){
constpageType=mw.config.get('wgCanonicalSpecialPageName');
if(!['Contributions','IPContributions'].includes(pageType))return;
constcfg=mw.config.get();
$('li[data-mw-revid]').each(asyncfunction(){
const$li=$(this);
constrevid=$li.data('mw-revid');
if(!revid)return;
letpage=mw.config.get('wgPageName');
const$titleEl=$li.find('.mw-contributions-title, .mw-title, .mw-contrib-title').first();
if($titleEl.length){
constt=$titleEl.text().trim();
if(t)page=t.replace(/ /g,'_');
}
lettargetUser=mw.config.get('wgRelevantUserName')||'';
const$userlink=$li.find('.mw-userlink, .mw-contrib-username, .mw-contributions-username').first();
if($userlink.length)targetUser=$userlink.text().trim()||targetUser;
if(!targetUser)return;
if($li.data('foxtools-processed'))return;
letlatestRevId=null;
try{
latestRevId=awaitgetLatestRevId(page);
}catch(err){
console.warn('Gagal mendapatkan revisi terbaru untuk',page,err);
return;
}
if(latestRevId!==revid)return;
letrevs=[];
try{
revs=awaitfetchRevisions(page,50);
}catch(err){
console.warn('Gagal fetch revisions',err);
}
constlastGoodRevId=findLastGoodRevIdFromRevisions(revs,revid,targetUser);
consteditCount=countConsecutiveEdits(revs,revid,targetUser);
attachButtonsToListItem($li,page,revid,targetUser,editCount,lastGoodRevId);
$li.data('foxtools-processed',true);
});
}
asyncfunctionaddFoxRollbackInHistory(){
if(mw.config.get('wgAction')!=='history')return;
constpage=mw.config.get('wgPageName');
const$rows=$('li[data-mw-revid]');
if(!$rows.length)return;
letlatest;
try{
latest=awaitgetLatestRevId(page);
}catch(err){
console.warn('Gagal mendapatkan revisi terbaru',err);
return;
}
const$top=$rows.first();
consttopRevid=$top.data('mw-revid');
consttopUser=$top.find('.mw-userlink').text().trim();
if(topRevid===latest){
letrevs=[];
try{
revs=awaitfetchRevisions(page,'max');
}catch(err){
console.warn('Gagal fetch revisions for history',err);
}
constlastGoodTop=findLastGoodRevIdFromRevisions(revs,topRevid,topUser);
attachHistoryButtons($top,page,topRevid,topUser,lastGoodTop);
}else{
if($top.data('foxtools-restore-added'))return;
$top.data('foxtools-restore-added',true);
constrevid=topRevid;
constrestorePanel=document.createElement('span');
restorePanel.className='foxtools-restore';
restorePanel.style.marginLeft='8px';
constbtnRestore=mkButton('Pulihkan revisi','mw-ui-button mw-ui-progressive');
btnRestore.onclick=async(e)=>{
e.preventDefault();
e.stopPropagation();
try{
constcomment=askComment();
if(comment===null)return;
consttargetUser=awaitgetUserOfRevision(revid);
constsummary=summaryRestoreToTarget(page,revid,targetUser,comment);
awaitfoxUndoRollback(page,latest,revid,summary);
notiOK(`🟢 Halaman berhasil dipulihkan ke revisi ${revid}`);
location.reload();
}catch(err){
console.error(err);
notiWARN(`⚠️ Gagal memulihkan ke revisi ${revid}`);
}
};
restorePanel.appendChild(btnRestore);
const$tag=$top.find('.mw-tag-markers').first();
if($tag.length){
$tag.before(restorePanel);
}else{
$top.append(restorePanel);
}
}
$rows.each(function(){
const$row=$(this);
if($row.is($top))return;
if($row.find('.foxtools-restore-only').length)return;
constrevid=$row.data('mw-revid');
constrestorePanel=document.createElement('span');
restorePanel.className='foxtools-restore-only';
restorePanel.style.marginLeft='8px';
constbtnRestore=mkButton('Pulihkan revisi','mw-ui-button mw-ui-progressive');
btnRestore.onclick=async(e)=>{
e.preventDefault();
e.stopPropagation();
try{
constcomment=askComment();
if(comment===null)return;
consttargetUser=awaitgetUserOfRevision(revid);
constsummary=summaryRestoreToTarget(page,revid,targetUser,comment);
awaitfoxUndoRollback(page,latest,revid,summary);
notiOK(`🟢 Halaman berhasil dipulihkan ke revisi ${revid}`);
location.reload();
}catch(err){
console.error(err);
notiWARN(`⚠️ Gagal memulihkan ke revisi ${revid}`);
}
};
restorePanel.appendChild(btnRestore);
const$tag=$row.find('.mw-tag-markers').first();
if($tag.length){
$tag.before(restorePanel);
}else{
$row.append(restorePanel);
}
});
}
asyncfunctionattachDiffButtons(){
constpage=mw.config.get('wgPageName');
constdiffId=Number(mw.util.getParamValue('diff'));
constoldId=Number(mw.util.getParamValue('oldid'));
if(!diffId)return;
constlatest=awaitgetLatestRevId(page);
constwaitForDiff=()=>newPromise(resolve=>{
constel=document.querySelector('#mw-content-text .diff');
if(el)returnresolve(el);
constobs=newMutationObserver((mutations,observer)=>{
constel2=document.querySelector('#mw-content-text .diff');
if(el2){
observer.disconnect();
resolve(el2);
}
});
obs.observe(document.body,{childList:true,subtree:true});
});
constdiffElement=awaitwaitForDiff();
letpanel=document.querySelector('.foxtools-diff-inline');
if(!panel){
panel=document.createElement('div');
panel.className='foxtools-diff-inline';
Object.assign(panel.style,{
display:'flex',
gap:'6px',
marginBottom:'6px'
});
diffElement.parentNode.insertBefore(panel,diffElement);
}else{
panel.innerHTML='';
}
constmakeBtn=(label,mwClass,onClick)=>{
constbtn=document.createElement('div');
btn.textContent=label;
btn.className=mwClass;
Object.assign(btn.style,{
cursor:'pointer',
padding:'4px 8px',
textAlign:'center'
});
btn.onclick=onClick;
returnbtn;
};
if(diffId===latest){
constbtnANB=makeBtn('Kembalikan (ANB)','mw-ui-button mw-ui-progressive');
constbtnNormal=makeBtn('Kembalikan','mw-ui-button mw-ui-destructive');
btnANB.onclick=async()=>{
constuser=awaitgetUserOfRevision(diffId);
awaitrollbackUser(page,diffId,user,true);
};
btnNormal.onclick=async()=>{
constuser=awaitgetUserOfRevision(diffId);
awaitrollbackUser(page,diffId,user,false);
};
panel.appendChild(btnANB);
panel.appendChild(btnNormal);
}else{
constbtnRestore=makeBtn('Pulihkan revisi','mw-ui-button mw-ui-progressive',async()=>{
constcomment=askComment();
if(comment===null)return;
consttargetUser=awaitgetUserOfRevision(diffId);
constsummary=summaryRestoreToTarget(page,diffId,targetUser,comment);
awaitfoxUndoRollback(page,latest,diffId,summary);
notiOK(`🟢 Halaman berhasil dipulihkan ke revisi ${diffId}`);
location.reload();
});
panel.appendChild(btnRestore);
}
}
constmodule={
name:'Rollback',
init(){
$(addFoxRollbackButtons);
$(addFoxRollbackInHistory);
$(attachDiffButtons);
constobserver=newMutationObserver(()=>{
try{
addFoxRollbackButtons();
addFoxRollbackInHistory();
attachDiffButtons();
}catch(e){}
});
observer.observe(document.body,{childList:true,subtree:true});
console.log('[FoxTools] Rollback module initialized.');
},
openPanel(){}
};
FT.register&&FT.register('Rollback',module);
})();
// </nowiki>
Konten disalin dari Wikipedia Bahasa Indonesia (lisensi CC BY-SA) Lihat versi asli di Wikipedia

Rekomendasi Pilihan