MediaWiki:Gadget-twinklefluff.js: Perbedaan antara revisi

Konten dihapus Konten ditambahkan
Tidak ada ringkasan suntingan
Repo at b425e01: twinklefluff.js
 
(9 revisi perantara oleh 3 pengguna tidak ditampilkan)
Baris 1:
// <nowiki>
 
 
(function($) {
 
 
Baris 9:
*** twinklefluff.js: Revert/rollback module
****************************************
* Mode of invocation: Links on historycontributions, contributionsrecent changes, history, and diff pages
* Active on: Diff pages, history pages, contributions pagesSpecial:RecentChanges(Linked),
and Special:Contributions
* Config directives in: TwinkleConfig
*/
 
Baris 18:
*/
 
Twinkle.fluff = function twinklefluff() {
// A list of usernames, usually only bots, that vandalism revert is jumped over; that is,
auto: function() {
// if vandalism revert was chosen on such username, then its target is on the revision before.
if( parseInt( Morebits.queryString.get('oldid'), 10) !== mw.config.get('wgCurRevisionId') ) {
// This is for handling quick bots that makes edits seconds after the original edit is made.
// not latest revision
// This only affects vandalism rollback; for good faith rollback, it will stop, indicating a bot
alert("Can't rollback, page has changed in the meantime.");
// has no faith, and for normal rollback, it will rollback that edit.
return;
Twinkle.fluff.trustedBots = [
'AnomieBOT',
'SineBot'
];
 
if (mw.config.get('wgIsProbablyEditable')) {
// Only proceed if the user can actually edit the page
// in question (ignored for contributions, see #632).
// wgIsProbablyEditable should take care of
// namespace/contentModel restrictions as well as
// explicit protections; it won't take care of
// cascading or TitleBlacklist restrictions
if (mw.config.get('wgDiffNewId') || mw.config.get('wgDiffOldId')) { // wgDiffOldId included for clarity in if else loop [[phab:T214985]]
mw.hook('wikipage.diff').add(function () { // Reload alongside the revision slider
Twinkle.fluff.addLinks.diff();
});
} else if (mw.config.get('wgAction') === 'view' && mw.config.get('wgCurRevisionId') !== mw.config.get('wgRevisionId')) {
Twinkle.fluff.addLinks.oldid();
} else if (mw.config.get('wgAction') === 'history') {
Twinkle.fluff.addLinks.history();
}
} else if (mw.config.get('wgNamespaceNumber') === -1) {
Twinkle.fluff.skipTalk = !Twinkle.getPref('openTalkPageOnAutoRevert');
Twinkle.fluff.rollbackInPlace = Twinkle.getPref('rollbackInPlace');
 
if (mw.config.get('wgCanonicalSpecialPageName') === 'Contributions') {
var vandal = $("#mw-diff-ntitle2").find("a.mw-userlink").text();
Twinkle.fluff.addLinks.contributions();
} else if (mw.config.get('wgCanonicalSpecialPageName') === 'Recentchanges' || mw.config.get('wgCanonicalSpecialPageName') === 'Recentchangeslinked') {
// Reload with recent changes updates
// structuredChangeFilters.ui.initialized is just on load
mw.hook('wikipage.content').add(function(item) {
if (item.is('div')) {
Twinkle.fluff.addLinks.recentchanges();
}
});
}
}
};
 
Twinkle.fluff.skipTalk = null;
Twinkle.fluff.revert( Morebits.queryString.get( 'twinklerevert' ), vandal, true );
Twinkle.fluff.rollbackInPlace = null;
 
// Consolidated construction of fluff links
Twinkle.fluff.linkBuilder = {
spanTag: function(color, content) {
var span = document.createElement('span');
span.style.color = color;
span.appendChild(document.createTextNode(content));
return span;
},
normal: function() {
 
var spanTag = buildLink: function( color, content text) {
var spanlink = document.createElement( 'spana' );
link.appendChild(Twinkle.fluff.linkBuilder.spanTag('Black', '['));
span.style.color = color;
spanlink.appendChild( documentTwinkle.createTextNodefluff.linkBuilder.spanTag(color, content text) );
link.appendChild(Twinkle.fluff.linkBuilder.spanTag('Black', ']'));
return span;
link.href = '#';
};
return link;
},
 
/**
if( mw.config.get('wgNamespaceNumber') === -1 && mw.config.get('wgCanonicalSpecialPageName') === "Contributions" ) {
* @param {string} vandal - Username of the editor being reverted (required)
//Get the username these contributions are for
* @param {boolean} inline - True to create two links in a span, false
var logLink = $('#contentSub').find('a[title^="Special:Log"]').last();
* to create three links in a div (optional)
if (logLink.length>0) //#215 -- there is no log link on Special:Contributions with no user
* @param {number|string} [rev=wgCurRevisionId] - Revision ID being reverted (optional)
{
* @param {string} [page=wgPageName] - Page being reverted (optional)
var username = decodeURIComponent(/wiki\/Special:Log\/(.+)$/.exec(logLink.attr("href").replace(/_/g, "%20"))[1]);
*/
if( Twinkle.getPref('showRollbackLinks').indexOf('contribs') !== -1 ||
rollbackLinks: function(vandal, inline, rev, page) {
( mw.config.get('wgUserName') !== username && Twinkle.getPref('showRollbackLinks').indexOf('others') !== -1 ) ||
var elem = inline ? 'span' : 'div';
( mw.config.get('wgUserName') === username && Twinkle.getPref('showRollbackLinks').indexOf('mine') !== -1 ) ) {
var revNode = document.createElement(elem);
var list = $("#mw-content-text").find("ul li:has(span.mw-uctop)");
 
rev = parseInt(rev, 10);
var revNode = document.createElement('strong');
if (rev) {
var revLink = document.createElement('a');
revLinkrevNode.appendChildsetAttribute( spanTag( 'Blackid', '[tw-revert' )+ rev);
} else {
revLink.appendChild( spanTag( 'SteelBlue', 'rollback' ) );
revLinkrevNode.appendChildsetAttribute( spanTag( 'Blackid', ']tw-revert' ) );
}
revNode.appendChild(revLink);
 
var revVandNodenormNode = document.createElement('strong');
var revVandLinkvandNode = document.createElement('astrong');
revVandLink.appendChild( spanTag( 'Black', '[' ) );
revVandLink.appendChild( spanTag( 'Red', 'vandalism' ) );
revVandLink.appendChild( spanTag( 'Black', ']' ) );
revVandNode.appendChild(revVandLink);
 
var normLink = Twinkle.fluff.linkBuilder.buildLink('SteelBlue', 'kembalikan');
list.each(function(key, current) {
var vandLink = Twinkle.fluff.linkBuilder.buildLink('Red', 'vandalisme');
var href = $(current).children("a:eq(1)").attr("href");
current.appendChild( document.createTextNode(' ') );
var tmpNode = revNode.cloneNode( true );
tmpNode.firstChild.setAttribute( 'href', href + '&' + Morebits.queryString.create( { 'twinklerevert': 'norm' } ) );
current.appendChild( tmpNode );
current.appendChild( document.createTextNode(' ') );
tmpNode = revVandNode.cloneNode( true );
tmpNode.firstChild.setAttribute( 'href', href + '&' + Morebits.queryString.create( { 'twinklerevert': 'vand' } ) );
current.appendChild( tmpNode );
});
}
}
} else {
 
$(normLink).click(function() {
if( mw.config.get('wgCanonicalSpecialPageName') === "Undelete" ) {
Twinkle.fluff.revert('norm', vandal, rev, page);
//You can't rollback deleted pages!
Twinkle.fluff.disableLinks(revNode);
return;
});
$(vandLink).click(function() {
Twinkle.fluff.revert('vand', vandal, rev, page);
Twinkle.fluff.disableLinks(revNode);
});
 
vandNode.appendChild(vandLink);
var firstRev = $("div.firstrevisionheader").length;
normNode.appendChild(normLink);
if( firstRev ) {
// we have first revision here, nothing to do.
return;
}
 
var separator = inline ? ' ' : ' || ';
var otitle, ntitle;
try {
var otitle1 = document.getElementById('mw-diff-otitle1');
var ntitle1 = document.getElementById('mw-diff-ntitle1');
if (!otitle1 || !ntitle1) {
return;
}
otitle = otitle1.parentNode;
ntitle = ntitle1.parentNode;
} catch( e ) {
// no old, nor new title, nothing to do really, return;
return;
}
 
if (!inline) {
var old_rev_url = $("#mw-diff-otitle1").find("strong a").attr("href");
var agfNode = document.createElement('strong');
var agfLink = Twinkle.fluff.linkBuilder.buildLink('DarkOliveGreen', 'kembalikan (AGF)');
$(agfLink).click(function() {
Twinkle.fluff.revert('agf', vandal, rev, page);
// Twinkle.fluff.disableLinks(revNode); // rollbackInPlace not relevant for any inline situations
});
agfNode.appendChild(agfLink);
revNode.appendChild(agfNode);
}
revNode.appendChild(document.createTextNode(separator));
revNode.appendChild(normNode);
revNode.appendChild(document.createTextNode(separator));
revNode.appendChild(vandNode);
 
return revNode;
// Lets first add a [edit this revision] link
var query = new Morebits.queryString( old_rev_url.split( '?', 2 )[1] );
 
},
var oldrev = query.get('oldid');
 
// Build [restore this revision] links
var revertToRevision = document.createElement('div');
restoreThisRevisionLink: function(revisionRef, inline) {
revertToRevision.setAttribute( 'id', 'tw-revert-to-orevision' );
// If not a specific revision number, should be wgDiffNewId/wgDiffOldId/wgRevisionId
revertToRevision.style.fontWeight = 'bold';
revisionRef = typeof revisionRef === 'number' ? revisionRef : mw.config.get(revisionRef);
 
var elem = inline ? 'span' : 'div';
var revertToRevisionLink = revertToRevision.appendChild( document.createElement('a') );
var revertToRevisionNode = document.createElement(elem);
revertToRevisionLink.href = "#";
$(revertToRevisionLink).click(function(){
Twinkle.fluff.revertToRevision(oldrev);
});
revertToRevisionLink.appendChild( spanTag( 'Black', '[' ) );
revertToRevisionLink.appendChild( spanTag( 'SaddleBrown', 'kembalikan ke versi ini' ) );
revertToRevisionLink.appendChild( spanTag( 'Black', ']' ) );
 
revertToRevisionNode.setAttribute('id', 'tw-revert-to-' + revisionRef);
otitle.insertBefore( revertToRevision, otitle.firstChild );
revertToRevisionNode.style.fontWeight = 'bold';
 
var revertToRevisionLink = Twinkle.fluff.linkBuilder.buildLink('SaddleBrown', 'kembalikan revisi ini');
if( document.getElementById('differences-nextlink') ) {
$(revertToRevisionLink).click(function() {
// Not latest revision
Twinkle.fluff.revertToRevision(revisionRef);
var new_rev_url = $("#mw-diff-ntitle1").find("strong a").attr("href");
});
query = new Morebits.queryString( new_rev_url.split( '?', 2 )[1] );
var newrev = query.get('oldid');
revertToRevision = document.createElement('div');
revertToRevision.setAttribute( 'id', 'tw-revert-to-nrevision' );
revertToRevision.style.fontWeight = 'bold';
revertToRevisionLink = revertToRevision.appendChild( document.createElement('a') );
revertToRevisionLink.href = "#";
$(revertToRevisionLink).click(function(){
Twinkle.fluff.revertToRevision(newrev);
});
revertToRevisionLink.appendChild( spanTag( 'Black', '[' ) );
revertToRevisionLink.appendChild( spanTag( 'SaddleBrown', 'restore this version' ) );
revertToRevisionLink.appendChild( spanTag( 'Black', ']' ) );
ntitle.insertBefore( revertToRevision, ntitle.firstChild );
 
if (inline) {
return;
revertToRevisionNode.appendChild(document.createTextNode(' '));
}
revertToRevisionNode.appendChild(revertToRevisionLink);
return revertToRevisionNode;
}
};
 
 
Twinkle.fluff.addLinks = {
contributions: function() {
// $('sp-contributions-footer-anon-range') relies on the fmbox
// id in [[MediaWiki:Sp-contributions-footer-anon-range]] and
// is used to show rollback/vandalism links for IP ranges
if (mw.config.exists('wgRelevantUserName') || !!$('#sp-contributions-footer-anon-range')[0]) {
// Get the username these contributions are for
var username = mw.config.get('wgRelevantUserName');
if (Twinkle.getPref('showRollbackLinks').indexOf('contribs') !== -1 ||
(mw.config.get('wgUserName') !== username && Twinkle.getPref('showRollbackLinks').indexOf('others') !== -1) ||
(mw.config.get('wgUserName') === username && Twinkle.getPref('showRollbackLinks').indexOf('mine') !== -1)) {
var list = $('#mw-content-text').find('ul li:has(span.mw-uctop):has(.mw-changeslist-diff)');
 
list.each(function(key, current) {
// revid is also available in the href of both
// .mw-changeslist-date or .mw-changeslist-diff
var page = $(current).find('.mw-contributions-title').text();
current.appendChild(Twinkle.fluff.linkBuilder.rollbackLinks(username, true, current.dataset.mwRevid, page));
});
}
}
if( Twinkle.getPref('showRollbackLinks').indexOf('diff') !== -1 ) {
},
var vandal = $("#mw-diff-ntitle2").find("a").first().text();
 
recentchanges: function() {
var revertNode = document.createElement('div');
if (Twinkle.getPref('showRollbackLinks').indexOf('recent') !== -1) {
revertNode.setAttribute( 'id', 'tw-revert' );
// Latest and revertable (not page creations, logs, categorizations, etc.)
var list = $('.mw-changeslist .mw-changeslist-last.mw-changeslist-src-mw-edit');
// Exclude top-level header if "group changes" preference is used
// and find only individual lines or nested lines
list = list.not('.mw-rcfilters-ui-highlights-enhanced-toplevel').find('.mw-changeslist-line-inner, td.mw-enhanced-rc-nested');
 
list.each(function(key, current) {
var agfNode = document.createElement('strong');
var vandNodevandal = document$(current).createElementfind('strong.mw-userlink').text();
var normNodehref = document$(current).find('.mw-changeslist-diff').createElementattr('stronghref');
var rev = mw.util.getParamValue('diff', href);
var page = current.dataset.targetPage;
current.appendChild(Twinkle.fluff.linkBuilder.rollbackLinks(vandal, true, rev, page));
});
}
},
 
history: function() {
var agfLink = document.createElement('a');
if (Twinkle.getPref('showRollbackLinks').indexOf('history') !== -1) {
var vandLink = document.createElement('a');
// All revs
var normLink = document.createElement('a');
var histList = $('#pagehistory li').toArray();
 
// On first page of results, so add revert/rollback
agfLink.href = "#";
// links to the top revision
vandLink.href = "#";
if (!$('.mw-firstlink').length) {
normLink.href = "#";
var first = histList.shift();
$(agfLink).click(function(){
var vandal = first.querySelector('.mw-userlink').text;
Twinkle.fluff.revert('agf', vandal);
});
$(vandLink).click(function(){
Twinkle.fluff.revert('vand', vandal);
});
$(normLink).click(function(){
Twinkle.fluff.revert('norm', vandal);
});
 
agfLinkfirst.appendChild( spanTagTwinkle.fluff.linkBuilder.rollbackLinks( 'Black'vandal, '[' true) );
}
agfLink.appendChild( spanTag( 'DarkOliveGreen', 'kembalikan (ANB)' ) );
agfLink.appendChild( spanTag( 'Black', ']' ) );
 
// oldid
vandLink.appendChild( spanTag( 'Black', '[' ) );
histList.forEach(function(rev) {
vandLink.appendChild( spanTag( 'Red', 'kembalikan (VANDAL)' ) );
// From restoreThisRevision, non-transferable
vandLink.appendChild( spanTag( 'Black', ']' ) );
 
var href = rev.querySelector('.mw-changeslist-date').href;
normLink.appendChild( spanTag( 'Black', '[' ) );
var oldid = parseInt(mw.util.getParamValue('oldid', href), 10);
normLink.appendChild( spanTag( 'SteelBlue', 'kembalikan' ) );
normLink.appendChild( spanTag( 'Black', ']' ) );
 
agfNoderev.appendChild(agfLinkTwinkle.fluff.linkBuilder.restoreThisRevisionLink(oldid, true));
});
vandNode.appendChild(vandLink);
normNode.appendChild(normLink);
 
revertNode.appendChild( agfNode );
revertNode.appendChild( document.createTextNode(' || ') );
revertNode.appendChild( normNode );
revertNode.appendChild( document.createTextNode(' || ') );
revertNode.appendChild( vandNode );
 
}
ntitle.insertBefore( revertNode, ntitle.firstChild );
},
 
diff: function() {
// Autofill user talk links on diffs with vanarticle for easy warning, but don't autowarn
var warnFromTalk = function(xtitle) {
var talkLink = $('#mw-diff-' + xtitle + '2 .mw-usertoollinks a').first();
if (talkLink.length) {
var extraParams = 'vanarticle=' + mw.util.rawurlencode(Morebits.pageNameNorm) + '&' + 'noautowarn=true';
// diffIDs for vanarticlerevid
extraParams += '&vanarticlerevid=';
extraParams += xtitle === 'otitle' ? mw.config.get('wgDiffOldId') : mw.config.get('wgDiffNewId');
 
var href = talkLink.attr('href');
if (href.indexOf('?') === -1) {
talkLink.attr('href', href + '?' + extraParams);
} else {
talkLink.attr('href', href + '&' + extraParams);
}
}
};
 
// Older revision
warnFromTalk('otitle'); // Add quick-warn link to user talk link
// Don't load if there's a single revision or weird diff (cur on latest)
if (mw.config.get('wgDiffOldId') && (mw.config.get('wgDiffOldId') !== mw.config.get('wgDiffNewId'))) {
// Add a [restore this revision] link to the older revision
var oldTitle = document.getElementById('mw-diff-otitle1').parentNode;
oldTitle.insertBefore(Twinkle.fluff.linkBuilder.restoreThisRevisionLink('wgDiffOldId'), oldTitle.firstChild);
}
 
// Newer revision
warnFromTalk('ntitle'); // Add quick-warn link to user talk link
// Add either restore or rollback links to the newer revision
// Don't show if there's a single revision or weird diff (prev on first)
if (document.getElementById('differences-nextlink')) {
// Not latest revision, add [restore this revision] link to newer revision
var newTitle = document.getElementById('mw-diff-ntitle1').parentNode;
newTitle.insertBefore(Twinkle.fluff.linkBuilder.restoreThisRevisionLink('wgDiffNewId'), newTitle.firstChild);
} else if (Twinkle.getPref('showRollbackLinks').indexOf('diff') !== -1 && mw.config.get('wgDiffOldId') && (mw.config.get('wgDiffOldId') !== mw.config.get('wgDiffNewId') || document.getElementById('differences-prevlink'))) {
var vandal = $('#mw-diff-ntitle2').find('a').first().text();
var ntitle = document.getElementById('mw-diff-ntitle1').parentNode;
 
ntitle.insertBefore(Twinkle.fluff.linkBuilder.rollbackLinks(vandal), ntitle.firstChild);
}
},
 
oldid: function() { // Add a [restore this revision] link on old revisions
var revisionInfo = document.getElementById('mw-revision-info');
if (!revisionInfo) {
return;
}
var title = revisionInfo.parentNode;
title.insertBefore(Twinkle.fluff.linkBuilder.restoreThisRevisionLink('wgRevisionId'), title.firstChild);
}
};
 
Twinkle.fluff.revertdisableLinks = function revertPagedisablelinks( type, vandal, autoRevert, rev, page parentNode) {
// Array.from not available in IE11 :(
$(parentNode).children().each(function(_ix, node) {
node.innerHTML = node.textContent; // Feels like cheating
$(node).css('font-weight', 'normal').css('color', 'darkgray');
});
};
 
 
Twinkle.fluff.revert = function revertPage(type, vandal, rev, page) {
if (mw.util.isIPv6Address(vandal)) {
vandal = Morebits.sanitizeIPv6(vandal);
Baris 209 ⟶ 306:
var revid = rev || mw.config.get('wgCurRevisionId');
 
if (Twinkle.fluff.rollbackInPlace) {
Morebits.status.init( document.getElementById('mw-content-text') );
var notifyStatus = document.createElement('span');
$( '#catlinks' ).remove();
mw.notify(notifyStatus, {
autoHide: false,
title: 'Rollback on ' + page,
tag: 'twinklefluff_' + rev // Shouldn't be necessary given disableLink
});
Morebits.status.init(notifyStatus);
} else {
Morebits.status.init(document.getElementById('mw-content-text'));
$('#catlinks').remove();
}
 
var params = {
Baris 216 ⟶ 323:
user: vandal,
pagename: pagename,
revid: revid,
autoRevert: !!autoRevert
};
var query = {
Baris 223 ⟶ 329:
'prop': ['info', 'revisions', 'flagged'],
'titles': pagename,
'intestactions': 'edit',
'rvlimit': 50, // max possible
'rvlimit': 50, // intentionally limited
'rvprop': [ 'ids', 'timestamp', 'user', 'comment' ],
'intokencurtimestamp': 'edit',
'meta': 'tokens',
'type': 'csrf'
};
var wikipedia_api = new Morebits.wiki.api( 'Mengambil data revisi yang lebih awal', query, Twinkle.fluff.callbacks.main );
wikipedia_api.params = params;
wikipedia_api.post();
};
 
Twinkle.fluff.revertToRevision = function revertToRevision( oldrev ) {
 
Morebits.status.init( document.getElementById('mw-content-text') );
 
var query = {
'action': 'query',
'prop': ['info', 'revisions'],
'titles': mw.config.get('wgPageName'),
'rvlimit': 1,
'rvstartid': oldrev,
'rvprop': [ 'ids', 'timestamp', 'user', 'comment' ],
'intokenformat': 'editxml',
'formatcurtimestamp': 'xml',
'meta': 'tokens',
'type': 'csrf'
};
var wikipedia_api = new Morebits.wiki.api( 'Mengambil data revisi yang lebih awal', query, Twinkle.fluff.callbacks.toRevision.main );
wikipedia_api.params = { rev: oldrev };
wikipedia_api.post();
};
 
Twinkle.fluff.userIpLink = function( user ) {
return (Morebitsmw.util.isIPAddress(user) ? "'[[Special:Contributions/"' : "'[[:User:" ') + user + "'|"' + user + "']]"';
};
 
Twinkle.fluff.callbacks = {
toRevision: function(apiobj) {
var xmlDoc = apiobj.responseXML;
main: function( self ) {
var xmlDoc = self.responseXML;
 
var lastrevid = parseInt( $(xmlDoc).find('page').attr('lastrevid'), 10);
var touched = $(xmlDoc).find('page').attr('touched');
var starttimestamploadtimestamp = $(xmlDoc).find('pageapi').attr('starttimestampcurtimestamp');
var edittokencsrftoken = $(xmlDoc).find('pagetokens').attr('edittokencsrftoken');
var revertToRevID = parseInt($(xmlDoc).find('rev').attr('revid'), 10);
var revertToUser = $(xmlDoc).find('rev').attr('user');
 
if (revertToRevID !== selfapiobj.params.rev) {
selfapiobj.statitemstatelem.error( 'TheRevisi retrievedyang revisiondiambil doestidak notcocok matchdengan therevisi requestedyang revisiondiminta. Menghentikan Abortingpengembalian.' );
return;
}
 
var optional_summary = prompt( "'Mohon berikanberi alasan pengembalian: "', "" ''); // padded out to widen prompt in Firefox
if (optional_summary === null) {
apiobj.statelem.error('Dibatalkan oleh pengguna.');
{
return;
self.statelem.error( 'Dibatalkan pengguna.' );
}
return;
var summary = Twinkle.fluff.formatSummary('Dikembalikan ke revisi ' + revertToRevID + ' oleh $USER', revertToUser, optional_summary);
}
var summary = Twinkle.fluff.formatSummary("Dikembalikan ke revisi " + revertToRevID + " oleh $USER", revertToUser, optional_summary);
 
var query = {
'action': 'edit',
'title': mw.config.get('wgPageName'),
'summary': summary,
'token': edittokencsrftoken,
'undo': lastrevid,
'undoafter': revertToRevID,
'basetimestamp': touched,
'starttimestamp': starttimestamploadtimestamp,
'watchlist': Twinkle.getPref('watchRevertedPages').indexOf( self.params.type 'torev') !== -1 ? 'watch' : undefined,
'minor': Twinkle.getPref('markRevertedPagesAsMinor').indexOf( self.params.type 'torev') !== -1 ? true : undefined
};
 
Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName');
Morebits.wiki.actionCompleted.notice = "'Pengembalian selesai"';
 
var wikipedia_api = new Morebits.wiki.api( 'Menyimpan isikonten yang terkembalikandikembalikan', query, Twinkle.fluff.callbacks.complete, selfapiobj.statelem);
wikipedia_api.params = selfapiobj.params;
wikipedia_api.post();
 
}
},
main: function( self apiobj) {
var xmlDoc = selfapiobj.responseXML;
 
varif lastrevid = parseInt(typeof $(xmlDoc).find('pageactions').attr('lastrevidedit'), 10=== 'undefined'); {
apiobj.statelem.error('Tidak bisa menyunting halaman, kemungkinan dilindungi.');
return;
}
 
var lastrevid = parseInt($(xmlDoc).find('page').attr('lastrevid'), 10);
var touched = $(xmlDoc).find('page').attr('touched');
var starttimestamploadtimestamp = $(xmlDoc).find('pageapi').attr('starttimestampcurtimestamp');
var edittokencsrftoken = $(xmlDoc).find('pagetokens').attr('edittokencsrftoken');
var lastuser = $(xmlDoc).find('rev').attr('user');
 
var revs = $(xmlDoc).find('rev');
 
var statelem = apiobj.statelem;
if( revs.length < 1 ) {
var params = apiobj.params;
self.statelem.error( 'Hanya ada kurang dari satu revisi tambahan, oleh karena itu tidak bisa melakukan pengembalian' );
 
if (revs.length < 1) {
statelem.error('Tidak memiliki satu pun revisi tambahan, sehingga tidak mungkin untuk dikembalikan.');
return;
}
var top = revs[0];
if ( lastrevid < self.params.revid ) {
Morebits.status.error( 'Error', [ 'ThePenanda mostrevisi recentterakhir revisionyang IDdiperoleh receiveddari from the serverpeladen, ', Morebits.htmlNode( 'strong', lastrevid ), ', iskurang lessdari thanpenanda therevisi IDyang ofsaat theini displayed revisionditampilkan. ThisIni couldmenandakan indicatebahwa thatrevisi thesaat currentini revisionsudah has been deleteddihapus, thepeladen serversedang is laggingtersendat, or that badatau data hasburuk beenyang receivedditerima. WillProses stopaka proceeding at this pointdihentikan.' ] );
return;
}
var index = 1;
if ( self.params.revid !== lastrevid ) {
Morebits.status.warn( 'WarningPeringatan', [ 'LatestRevisi revisionterakhir ', Morebits.htmlNode( 'strong', lastrevid ), ' doesn\'ttidak sesuai equaldengan ourrevisi revisionkami ', Morebits.htmlNode( 'strong', self.params.revid ) ] );
if ( lastuser === self.params.user ) {
switch ( self.params.type ) {
case 'vand':
Morebits.status.info( 'InfoInformasi', [ 'LatestRevisi revisionterakhir wasdibuat made byoleh ', Morebits.htmlNode( 'strong', self.params.user ) , '. AsKarena wedianggap assumesebagai vandalismvandalisme, wekami continuelanjutkan to revertpengembaliannya.' ]);
break;
case 'agf':
Morebits.status.warn( 'Warning', [ 'LatestRevisi revisionterakhir wasdibuat made byoleh ', Morebits.htmlNode( 'strong', self.params.user ) , '. AsKarena wedianggap assumesebagai goodniat faithbaik, wepengembalian stopini revertingdihentikan, as thedi problemmana mightmasalah havemungkin beendapat fixeddiatasi.' ]);
return;
default:
Morebits.status.warn( 'NoticePerhatian', [ 'LatestRevisi revisionterakhir wasdibuat made byoleh ', Morebits.htmlNode( 'strong', self.params.user ) , ', butnamun wekami willakan stopmenghentikan revertingproses anywaypengembalian.' ] );
return;
}
} else if (params.type === 'vand' &&
}
Twinkle.fluff.trustedBots.indexOf(top.getAttribute('user')) !== -1 && revs.length > 1 &&
else if(self.params.type === 'vand' &&
Twinkle.fluff.whiteList.indexOf( toprevs[1].getAttribute( 'userpageId' ) ) !=== -1 && revsparams.length > 1revid) &&{
Morebits.status.info('Informasi', [ 'Revisi terakhir dibuat oleh ', Morebits.htmlNode('strong', lastuser), ', bot yang tepercaya, dan revisi sebelumnya dibuat oleh pengguna vandalisme, pengembalian dilanjutkan.' ]);
revs[1].getAttribute( 'pageId' ) === self.params.revid) {
Morebits.status.info( 'Info', [ 'Latest revision was made by ', Morebits.htmlNode( 'strong', lastuser ), ', a trusted bot, and the revision before was made by our vandal, so we proceed with the revert.' ] );
index = 2;
} else {
Morebits.status.error( 'ErrorGalat', [ 'LatestRevisi revisionterakhir wasdibuat made byoleh ', Morebits.htmlNode( 'strong', lastuser ), ', sosehingga itmungkin mighttelah havedikembalikan, alreadyakan beenmenghentikan reverted,pengembalian stopping revertingini.'] );
return;
}
Baris 350 ⟶ 465:
}
 
if( (Twinkle.fluff.whiteListtrustedBots.indexOf( self.params.user ) !== -1 ) {
switch ( self.params.type ) {
case 'vand':
Morebits.status.info( 'Info', [ 'VandalismPengembalian revertvandalisme wasdipilih chosen onpada ', Morebits.htmlNode( 'strong', self.params.user ), '. AsKarena thisbot isini a whitelistedmerupakan bot tepercaya, wekami assumemenganggap youAnda wantedakan tomengembalikan revertvandalisme vandalismyang madedibuat byoleh thepengguna previous user insteadsebelumnya.' ] );
index = 2;
self. params.user = revs[1].getAttribute( 'user' );
break;
case 'agf':
Morebits.status.warn( 'NoticePemberitahuan', [ 'GoodPengembalian faithdengan revertniat wasbaik chosendipilih onpada ', Morebits.htmlNode( 'strong', self.params.user ), '. ThisIni isadalah abot whitelisted bottepercaya, anddan sincekarena botsbot havetidak nopunya faithniat, AGFpengembalian rollbackANB willtidak not proceeddilanjutkan.' ] );
return;
case 'norm':
/* falls through */
default:
var cont = confirm( 'NormalPengembalian revertnormal wassudah chosendipilih, butnamun thesuntingan mostterakhir recentdibuat editoleh wasbot made by a whitelisted bottepercaya (' + self.params.user + '). DoIngin youmelanjutkan wantrevisi tosebelumnya revert the revision before insteadsaja?' );
if ( cont ) {
Morebits.status.info( 'Info', [ 'NormalPengembalian revertnormal wasdipilih chosen onpada ', Morebits.htmlNode( 'strong', self.params.user ), '. ThisIni isadalah abot whitelisted bottepercaya, anddan perdengan confirmationkonfirmasi, we\'llkami revertakan themengembalikan previousrevisi revisionsebelumnya insteadsaja.' ] );
index = 2;
self. params.user = revs[1].getAttribute( 'user' );
} else {
Morebits.status.warn( 'NoticePemberitahuan', [ 'NormalPengembalian revertnormal wasdipilih chosen onpada ', Morebits.htmlNode( 'strong', self.params.user ), '. ThisIni isadalah abot whitelisted bottepercaya, butnamun perdengan confirmationkonfirmasi, revertpengembalian onrevisi topatas revisionakan will proceeddiproses.' ] );
}
break;
}
}
Baris 377 ⟶ 492:
var count = 0;
 
for( (var i = index; i < revs.length; ++i ) {
++count;
if( (revs[i].getAttribute( 'user' ) !== self.params.user ) {
found = i;
break;
Baris 385 ⟶ 500:
}
 
if ( ! found ) {
self.statelem.error( [ 'Tidak dapat ditemukan revisi sebelumnya. Bisa jadiMungkin ', Morebits.htmlNode( 'strong', self.params.user ), ' adalah satu-satunya penyunting, atau pengguna tersebut telah melakukan ' + Twinkle.getPref('revertMaxRevisions') + ' suntingan berturut-turut.' ] );
return;
}
 
if ( ! count ) {
Morebits.status.error( 'ErrorGalat', "'Tidak bisa membatalkan nol revisi. Ini mungkin dikarenakan revisi tersebut telah dibatalkan namun IDpenanda revisi masih tetap sama." ');
return;
}
 
var good_revision = revs[ found ];
var userHasAlreadyConfirmedAction = false;
if (self.params.type !== 'vand' && count > 1) {
if ( !confirm( self.params.user + ' telah melakukan ' + count + ' suntingan berturut-turut. Apakah Anda yakin mau membatalkan semuanya?') ) {
Morebits.status.info( 'Notice', 'MenghentinkanMenghentikan pembatalan karena input dari pengguna.' );
return;
}
Baris 405 ⟶ 520:
}
 
self.params.count = count;
 
self.params.goodid = good_revision.getAttribute( 'revid' );
self.params.gooduser = good_revision.getAttribute( 'user' );
 
self.statelem.status( [ ' revisi ', Morebits.htmlNode( 'strong', self.params.goodid ), ' yang dilakukan ', Morebits.htmlNode( 'strong', count ), ' suntingan yang lalu oleh ', Morebits.htmlNode( 'strong', self.params.gooduser ) ] );
 
var summary, extra_summary;
switch ( self.params.type ) {
case 'agf':
extra_summary = prompt( "'Komentar tambahan untuk ringkasan suntingan: "', "" ''); // padded out to widen prompt in Firefox
if (extra_summary === null) {
statelem.error('Dibatalkan oleh pengguna.');
{
return;
self.statelem.error( 'Dibatalkan oleh pengguna.' );
return;}
userHasAlreadyConfirmedAction = true;
}
userHasAlreadyConfirmedAction = true;
 
summary = Twinkle.fluff.formatSummary("'Membatalkan suntingan [[WP:ANB|berniat baik]] oleh $USER"', self.params.user, extra_summary);
break;
 
case 'vand':
 
summary = "'Membatalkan "' + self.params.count + "(params.count > 1 ? ' suntingan' : ' suntingan') + ' oleh [[Special:Contributions/"' +
self.params.user + "'|"' + self.params.user + "']] ([[User talk:"' + self.params.user + "'|bicara]]) ke revisi terakhir oleh "' +
self.params.gooduser + "." + Twinkle.getPref('summaryAd');
break;
 
case 'norm':
/* falls through */
default:
if ( Twinkle.getPref('offerReasonOnNormalRevert') ) {
extra_summary = prompt( "'Komentar tambahan untuk ringkasan suntingan: "', "" ''); // padded out to widen prompt in Firefox
if (extra_summary === null) {
statelem.error('Dibatalkan oleh pengguna.');
{
return;
self.statelem.error( 'Dibatalkan oleh pengguna.' );
return;}
userHasAlreadyConfirmedAction = true;
}
userHasAlreadyConfirmedAction = true;
}
 
summary = Twinkle.fluff.formatSummary("'Membatalkan "' + selfparams.count + (params.count > 1 ? ' suntingan' : ' suntingan') +
"' suntingan olehby $USER"', self.params.user, extra_summary);
break;
}
 
if (Twinkle.getPref('confirmOnFluff') && !userHasAlreadyConfirmedAction && !confirm("'Membatalkan halaman: apakah Anda yakin?"')) {
self.statelem.error( 'Dibatalkan oleh pengguna.' );
return;
}
 
// Decide whether to notify the user on success
var query;
if( (!selfTwinkle.paramsfluff.autoRevertskipTalk ||&& Twinkle.getPref('openTalkPageOnAutoRevertopenTalkPage').indexOf(params.type) !== -1 &&
mw.config.get('wgUserName') !== params.user) {
Twinkle.getPref('openTalkPage').indexOf( self.params.type ) !== -1 &&
params.notifyUser = true;
mw.config.get('wgUserName') !== self.params.user ) {
Morebits.status.info( 'Info', [ 'Membuka halaman penyuntingan halaman pembicaraan pengguna ', Morebits.htmlNode( 'strong', self.params.user ) ] );
 
query = {
'title': 'User talk:' + self.params.user,
'action': 'edit',
'preview': 'yes',
'vanarticle': self.params.pagename.replace(/_/g, ' '),
'vanarticlerevid': self.params.revid,
'vanarticlegoodrevid': self.params.goodid,
'type': self.params.type,
'count': self.params.count
};
 
switch( Twinkle.getPref('userTalkPageMode') ) {
case 'tab':
window.open( mw.util.wikiScript('index') + '?' + Morebits.queryString.create( query ), '_blank' );
break;
case 'blank':
window.open( mw.util.wikiScript('index') + '?' + Morebits.queryString.create( query ), '_blank',
'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800' );
break;
case 'window':
/* falls through */
default:
window.open( mw.util.wikiScript('index') + '?' + Morebits.queryString.create( query ),
( window.name === 'twinklewarnwindow' ? '_blank' : 'twinklewarnwindow' ),
'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800' );
break;
}
}
 
// figure out whether we need to/can review the edit
var $flagged = $(xmlDoc).find('flagged');
if ((Morebits.userIsInGroup('reviewer') || Morebits.userIsInGroup('sysop')userIsSysop) &&
$flagged.length &&
$flagged.attr("'stable_revid"') >= self.params.goodid &&
$flagged.attr("'pending_since"')) {
self.params.reviewRevert = true;
self.params.edittokencsrftoken = edittokencsrftoken;
}
 
var query = {
'action': 'edit',
'title': self.params.pagename,
'summary': summary,
'token': edittokencsrftoken,
'undo': lastrevid,
'undoafter': self.params.goodid,
'basetimestamp': touched,
'starttimestamp': starttimestamploadtimestamp,
'watchlist' : Twinkle.getPref('watchRevertedPages').indexOf( self.params.type ) !== -1 ? 'watch' : undefined,
'minor': Twinkle.getPref('markRevertedPagesAsMinor').indexOf( self.params.type ) !== -1 ? true : undefined
};
 
if (!Twinkle.fluff.rollbackInPlace) {
Morebits.wiki.actionCompleted.redirect = self.params.pagename;
Morebits.wiki.actionCompleted.noticeredirect = "Pembatalan selesai"params.pagename;
}
Morebits.wiki.actionCompleted.notice = 'Pembatalan selesai';
 
var wikipedia_api = new Morebits.wiki.api( 'Menyimpan isi yang telah dibatalkan', query, Twinkle.fluff.callbacks.complete, self.statelem);
wikipedia_api.params = self.params;
wikipedia_api.post();
 
},
complete: function (apiobj) {
// TODO Most of this is copy-pasted from Morebits.wiki.page#fnSaveSuccess. Unify it
var $edit = $(apiobj.getXML()).find('edit');
var blacklistxml = $editapiobj.attrgetXML('spamblacklist');
var $edit = $(xml).find('edit');
if (blacklist) {
 
var code = document.createElement('code');
if ($(xml).find('captcha').length > 0) {
code.style.fontFamily = "monospace";
apiobj.statelem.error('Could not rollback, because the wiki server wanted you to fill out a CAPTCHA.');
code.appendChild(document.createTextNode(blacklist));
apiobj.statelem.error(['Tidak dapat membatalkan karena URL ', code, ' berada dalam daftar hitam spam.']);
} else if ($edit.attr('nochange') === '') {
apiobj.statelem.warnerror("'Revisi yang dibatalkan sama dengan revisi terakhir: Tidak ada yang dapat dilakukan".');
} else {
apiobj.statelem.info("'done"');
var params = apiobj.params;
 
if (params.notifyUser) { // Only from main, not from toRevision
Morebits.status.info('Info', [ 'Opening user talk page edit form for user ', Morebits.htmlNode('strong', params.user) ]);
 
var windowQuery = {
'title': 'User talk:' + params.user,
'action': 'edit',
'preview': 'yes',
'vanarticle': params.pagename.replace(/_/g, ' '),
'vanarticlerevid': params.revid,
'vanarticlegoodrevid': params.goodid,
'type': params.type,
'count': params.count
};
 
switch (Twinkle.getPref('userTalkPageMode')) {
case 'tab':
window.open(mw.util.getUrl('', windowQuery), '_blank');
break;
case 'blank':
window.open(mw.util.getUrl('', windowQuery), '_blank',
'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800');
break;
case 'window':
/* falls through */
default:
window.open(mw.util.getUrl('', windowQuery),
window.name === 'twinklewarnwindow' ? '_blank' : 'twinklewarnwindow',
'location=no,toolbar=no,status=no,directories=no,scrollbars=yes,width=1200,height=800');
break;
}
}
 
 
// review the revert, if needed
Baris 540 ⟶ 659:
'action': 'review',
'revid': $edit.attr('newrevid'),
'token': apiobj.params.edittokencsrftoken,
'comment': Twinkle.getPref('summaryAd').trim()
};
Baris 555 ⟶ 674:
var result = builtInString;
 
// append user's custom reason with requisite punctuation
if (userString) {
result += ': ' + Morebits.string.toUpperCaseFirstChar(userString);
if (userString.search(/[.?!;]$/) === -1) {
result += '.';
}
} else {
result += '.';
}
result += Twinkle.getPref('summaryAd');
Baris 569 ⟶ 683:
// a contributions or contributions+talk link if it doesn't push the edit summary
// over the 255-byte limit
var resultLen = unescape(encodeURIComponent(result.replace("'$USER"', ""''))).length;
var contribsLink = "'[[Special:Contributions/"' + userName + "'|"' + userName + "']]"';
var contribsLen = unescape(encodeURIComponent(contribsLink)).length;
if (resultLen + contribsLen <= 255) {
var talkLink = "' ([[User talk:"' + userName + "'|bicara]])"';
if (resultLen + contribsLen + unescape(encodeURIComponent(talkLink)).length <= 255) {
result = resultMorebits.replacestring.safeReplace("result, '$USER"', contribsLink + talkLink);
} else {
result = resultMorebits.replacestring.safeReplace("result, '$USER"', contribsLink);
}
} else {
result = resultMorebits.replacestring.safeReplace("result, '$USER"', userName);
}
 
return result;
};
 
Twinkle.fluff.init = function twinklefluffinit() {
if (Twinkle.userAuthorized)
{
// A list of usernames, usually only bots, that vandalism revert is jumped over; that is,
// if vandalism revert was chosen on such username, then its target is on the revision before.
// This is for handling quick bots that makes edits seconds after the original edit is made.
// This only affects vandalism rollback; for good faith rollback, it will stop, indicating a bot
// has no faith, and for normal rollback, it will rollback that edit.
Twinkle.fluff.whiteList = [
'AnomieBOT',
'SineBot'
];
 
if ( Morebits.queryString.exists( 'twinklerevert' ) ) {
Twinkle.fluff.auto();
} else {
Twinkle.fluff.normal();
}
}
};
})(jQuery);
 
 
// </nowiki>