Difference between revisions 262272 and 263296 on ptwikibooks<!-- Início: Prefácio --> {{:{{PAGENAME}}/Prefácio}} <!-- Fim: Prefácio --> <!-- Início: Versões para impressão --> {| |- | {{livro}} | {{Versão para impressão}} |} <!-- Fim: Versões para impressão --> <!-- Início: Índice --> == Índice == {{:Wikilivros:Livros/{{PAGENAME}}}} <!-- Fim: Índice -->/** * Adds two links on pages like [[Special:AbuseLog/123]] to mark log entries as 'correct' or 'false positive' * (workaround for [[bugzilla:28213]] * @author: [[User:Helder.wiki]] * @tracking: [[Special:GlobalUsage/User:Helder.wiki/Tools/AbuseLogStatus.js]] ([[File:User:Helder.wiki/Tools/AbuseLogStatus.js]]) */ /*jshint browser: true, camelcase: false, curly: true, eqeqeq: true, immed: true, latedef: true, newcap: true, noarg: true, noempty: true, nonew: true, quotmark: true, undef: true, unused: true, strict: true, trailing: true, maxlen: 130, laxbreak: true, devel: true, evil: true, onevar: true */ /*global jQuery, mediaWiki */ ( function ( mw, $ ) { 'use strict'; /* Translatable strings */ mw.messages.set( { 'al-page-title': 'Wikipédia:Filtro_de_edições/Análise/$1/Registros', 'al-summary': 'Status do registro [[Special:AbuseLog/$1|$1]]: $2' + ' (edição feita com [[Special:PermaLink/36666969#Scripts|um script]])', 'al-correct-template': '*{' + '{Ação|$1}}\n', 'al-problem-template': '*{' + '{Ação|$1|erro=sim}}\n', 'al-correct-template-with-note': '*{' + '{Ação|$1|nota=$2}}\n', 'al-problem-template-with-note': '*{' + '{Ação|$1|erro=sim|nota=$2}}\n', // Keep this synced with the regex from [[User:Helder.wiki/Tools/AbuseFilterStats.js]] 'al-template-regex': '\\* *\\{\\{ *[Aa]ção *\\|(?:.*?\\D)?($1)(?:\\D.*?)?\\}\\} *(?:\\n|$)', 'al-analysis-page-regex': '^Wikipédia:Filtro de edições\\/Análise\\/(\\d+/\\d+)\\/Registros$', 'al-page-header': '{' + '{Lista de falsos positivos (cabeçalho)}}\n\n', 'al-section-title': 'Filtro $1', 'al-page-edit-success': '<p>A página <a href="$1">foi editada</a>.</p>', 'al-page-edit-conflict': 'Foi detectado um conflito entre edições. Por favor, tente novamente.', 'al-page-edit-error': 'Houve um erro ao tentar editar ($1). Por favor, tente novamente.', 'al-page-edit-error-unknown': 'Houve um erro desconhecido ao tentar editar. Por favor, tente novamente.', 'al-date-error': 'O script só funciona se o formato das datas não for alterado nas preferências.', 'al-page-content-error': 'A página de análises ainda não possui uma seção para este filtro ($1). ' + 'Crie manualmente as seções de cada filtro antes de enviar uma nova análise.', 'al-filter-count-error': 'Houve um erro ao tentar determinar quantos filtros existem atualmente ($1). ' + 'Crie manualmente a página de análises com uma seção para cada filtro antes de enviar uma ' + 'nova análise.', 'al-log-false-positive': 'Um editor já identificou que este registro foi um falso positivo', 'al-log-correct': 'Um editor já identificou que este registro estava correto', 'al-log-false-positive-note': 'Um editor já identificou que este registro foi um falso positivo: $1', 'al-log-correct-note': 'Um editor já identificou que este registro estava correto: $1', 'al-header': 'Análise', 'al-question': 'Este filtro deveria ter detectado esta ação?', 'al-specific-question': 'Foi correto classificar esta ação como "$1"?', 'al-correct-description': 'Marcar este registro como correto', 'al-yes': 'Sim', 'al-correct': 'Correto', 'al-incorrect-description': 'Marcar este registro como falso positivo', 'al-no': 'Não', 'al-incorrect': 'Falso positivo', 'al-placeholder': 'Observação sobre esta ação (se precisar)', 'al-submit': 'Enviar', 'al-submit-description': 'Enviar a sua análise (editará automaticamente a página apropriada)' } ); var api, filter, revision, reTemplate, reDetailsPage, reFilterLink, curLogs = {}; function getPeriodFromTimestamp( ts ){ var match, month, reDateNoPreference = /((?:jan|fever)eiro|março|abril|maio|ju[nl]ho|agosto|(?:setem|outu|novem|dezem)bro) de (\d{4})/; match = ts.match( reDateNoPreference ); if( match ){ month = $.inArray( match[1], mw.config.get( 'wgMonthNames' ) ); if ( month < 10){ month = '0' + month; } return match[2] + '/' + month; } mw.notify( mw.msg( 'al-date-error' ), { autoHide: false, tag: 'status' } ); return false; } function doEdit ( params ){ api.post( params ) .done( function( data ) { var edit = data.edit, link; if ( edit && edit.result && edit.result === 'Success' ) { link = mw.util.wikiGetlink( edit.title ) + '?diff=' + edit.newrevid; mw.notify( $( mw.msg( 'al-page-edit-success', link ) ), { autoHide: false, tag: 'status' } ); } else { mw.notify( mw.msg( 'al-page-edit-error-unknown' ), { autoHide: false, tag: 'status' } ); } } ) .fail( function( code ){ if( code === 'editconflict' ){ // TODO: Try again automatically (and no not remove the spinner during the process)! mw.notify( mw.msg( 'al-page-edit-conflict' ), { autoHide: false, tag: 'status' } ); return; } mw.notify( mw.msg( 'al-page-edit-error', code ), { autoHide: false, tag: 'status' } ); } ) .always( function(){ $.removeSpinner( 'af-status-spinner' ); $( '#al-submit' ).removeAttr( 'disabled' ); } ); } function onClick (){ var note, period, falsePositive = $( 'input[type="radio"]:checked' ).val() !== 'correct', defineStatus = function ( data ){ var template, start, text, editParams = { action: 'edit', title: mw.msg( 'al-page-title', period ), section: filter, summary: mw.msg( 'al-summary', revision, falsePositive ? mw.msg( 'al-incorrect' ) : mw.msg( 'al-correct' ) ), minor: true, watchlist: 'nochange', token: mw.user.tokens.get( 'editToken' ) }, page = data.query.pages[ data.query.pageids[0] ], isMissing = page.missing === ''; if ( note ){ note = note.replace( /\|/g, '{{!}}' ); template = falsePositive ? mw.message( 'al-problem-template-with-note', revision, note ).plain() : mw.message( 'al-correct-template-with-note', revision, note ).plain(); } else { template = falsePositive ? mw.message( 'al-problem-template', revision ).plain() : mw.message( 'al-correct-template', revision ).plain(); } if ( isMissing ){ api.get( { list: 'abusefilters', abfdir: 'older', abflimit: 1, abfprop: 'id' } ) .done( function( data ){ var i; text = mw.message( 'al-page-header' ).plain(); for( i = 1; i <= filter; i++ ){ text += '\n== ' + mw.msg( 'al-section-title', i ) + ' ==\n\n'; } text += '\n' + template; for(; i <= data.query.abusefilters[0].id; i++ ){ text += '\n== ' + mw.msg( 'al-section-title', i ) + ' ==\n\n'; } editParams.text = text; doEdit( editParams ); } ) .fail( function ( code, data ) { mw.notify( mw.msg( 'al-filter-count-error', data.error.info ), { autoHide: false, tag: 'status' } ); $.removeSpinner( 'af-status-spinner' ); } ); } else { text = page.revisions[0]['*']; text = text.replace( reTemplate, '' ) + '\n' + template; start = text.search( /^.*\{\{[Aa]ção/m ); text = text.substr( 0, start ).replace( /\n+$/g, '\n\n' ) + text.substr( start ) .split( '\n' ) .sort() .join( '\n' ) .replace( /^\n+/g, '' ) // TODO: remove these temporary hacks .replace( /(^|\n)\*\s+\{\{Ação/g, '$1*{' + '{Ação' ) .replace( /(\* *\{\{ *Ação *\| *(\d+)\D.+\n)(\* *\{\{ *Ação *\| *\2\D.+\n)+/g, '$1' ); editParams.basetimestamp = page.revisions[0].timestamp; editParams.starttimestamp = page.revisions[0].starttimestamp; editParams.text = text; doEdit( editParams ); } }, getPageContent = function (){ period = getPeriodFromTimestamp( $( 'fieldset' ).find( 'p:first span:first' ) .contents().first() .text() ); if( !period ){ $( '#al-submit' ).removeAttr( 'disabled' ); return; } $( '#al-submit' ).injectSpinner( 'af-status-spinner' ); $( '#mw-content-text' ).find( 'fieldset p > span > a' ).each( function(){ filter = $( this ).attr( 'href' ).match( /Especial:Filtro_de_abusos\/(\d+)$/ ); if( filter && filter[1] ){ filter = filter[1]; return false; } } ); api.get( { prop: 'info|revisions', rvprop: 'content|timestamp', intoken: 'edit', rvsection: filter, rvlimit: 1, indexpageids: true, titles: mw.msg( 'al-page-title', period ) } ) .done( defineStatus ) .fail( function ( code, data ) { if ( code === 'rvnosuchsection' ){ mw.notify( mw.msg( 'al-page-content-error', data.error.info ), { autoHide: false, tag: 'status' } ); } $.removeSpinner( 'af-status-spinner' ); } ); }; $( '#al-submit' ).attr( 'disabled', 'disabled' ); note = $( '#al-note' ).val(); mw.loader.using( [ 'mediawiki.api.edit', 'jquery.spinner', 'mediawiki.notify', 'mediawiki.notification' ], getPageContent ); } function addAbuseFilterStatusLinks(){ var desc = $( 'fieldset' ).find( 'p:first span:first' ) .text().match( /Descrição do filtro: (.+?) \(/ ); reTemplate = new RegExp( mw.message( 'al-template-regex', revision ).plain(), 'g' ); $( 'fieldset h3' ).first().before( $( '<h3>' ).text( mw.msg( 'al-header' ) ), $( '<p>' ).text( desc && desc[1] ? mw.msg( 'al-specific-question', desc[1] ) : mw.msg( 'al-question' ) ) .append( $( '<br />' ), $( '<input>' ).attr( { 'name': 'al-status', 'id': 'al-status-correct', 'type': 'radio', 'value': 'correct' } ).prop( 'checked', true ), $( '<label>' ).attr( { 'for': 'al-status-correct', 'title': mw.msg( 'al-correct-description' ) } ).text( mw.msg( 'al-yes' ) ), $( '<input>' ).attr( { 'name': 'al-status', 'id': 'al-status-incorrect', 'type': 'radio', 'value': 'incorrect' } ), $( '<label>' ).attr( { 'for': 'al-status-incorrect', 'title': mw.msg( 'al-incorrect-description' ) } ).text( mw.msg( 'al-no' ) ), ' ', $( '<input>' ).attr( { 'type': 'text', 'id': 'al-note', 'placeholder': mw.msg( 'al-placeholder' ), 'size': 50 } ), $( '<input>' ).attr( { 'type': 'submit', 'value': mw.msg( 'al-submit' ), 'id': 'al-submit', 'title': mw.msg( 'al-submit-description' ) } ).click( onClick ) ) ); } function markAbuseFilterEntriesByStatus( texts ){ mw.util.addCSS( '.af-log-false-positive { background: #FDD; } ' + '.af-log-correct { background: #DFD; }' ); $( '#mw-content-text' ).find( 'li' ).each( function(){ var log, $currentLi = $( this ); $currentLi.find( 'a' ).each( function(){ var note, period, match = $( this ).attr( 'href' ) .match( reDetailsPage ); if( match && match[1] ){ log = match[1]; reTemplate = new RegExp( mw.message( 'al-template-regex', log ).plain(), 'g' ); period = curLogs[ log ].timestamp.substring( 0, 4 ) + '/' + curLogs[ log ].timestamp.substring( 5, 7 ); match = texts[ period ].match( reTemplate ); if( match ){ note = match[0].match( /nota *= *(.+?) *(?:\||\}\} *(?:\n|$))/ ); // Highlight log entries already checked if( /\| *erro *= *sim/.test( match[0] ) ){ // add af-false-positive class $currentLi .addClass( 'af-log-false-positive' ) .attr( 'title', note ? mw.msg( 'al-log-false-positive-note', mw.html.escape( note[1] ) ) : mw.msg( 'al-log-false-positive' ) ); } else { $currentLi .addClass( 'af-log-correct' ) .attr( 'title', note ? mw.msg( 'al-log-correct-note', mw.html.escape( note[1] ) ) : mw.msg( 'al-log-correct' ) ); } } return false; } } ); } ); } function getSectionsFromPages( sections ){ var // key, section, // pages = [], revParams = { action: 'query', prop: 'revisions', rvprop: 'content' // ,indexpageids: true }; /* for( key in sections ){ pages.push( mw.msg( 'al-page-title', key ) ); if( sections[ key ].length === 1 ){ // FIXME: Get only one section } else { // Get the whole page } } */ revParams.titles = Object.keys( sections ).join( '|' ); api.get( revParams ) .done( function( data ){ var statusTexts = {}, reAnalysisPage = new RegExp( mw.message( 'al-analysis-page-regex' ).plain() ); $.each( data.query.pages, function( id ){ var period, pg = data.query.pages[ id ]; if ( pg.missing !== '' ){ period = pg.title.match( reAnalysisPage ); if( period && period[1] ){ statusTexts[ period[1] ] = pg.revisions[0]['*']; } } } ); markAbuseFilterEntriesByStatus( statusTexts ); } ); } function getPagesToCheck(){ var d, query = mw.Uri().query, // The log with the provided offset is returned // by the API but not by the special page // Adding +1 or -1 ensures the last item from the // special page is also returned by the API offset = query.dir === 'prev' ? 1 : -1, abuseLogParams = { action: 'query', list: 'abuselog', aflprop: 'ids|timestamp', afldir: query.dir === 'prev' ? 'newer' : 'older', afllimit: query.limit || 50 }; if( query.wpSearchUser ){ abuseLogParams.afluser = query.wpSearchUser; } if( query.wpSearchTitle ){ abuseLogParams.afltitle = query.wpSearchTitle; } if( query.wpSearchFilter ){ abuseLogParams.aflfilter = query.wpSearchFilter; } // FIXME: Is this correct? Are the other values of 'dir'? if( query.offset ){ d = query.offset; d = new Date( Date.UTC( d.substring( 0, 4 ), d.substring( 4, 6 ) - 1, d.substring( 6, 8 ), d.substring( 8, 10 ), d.substring( 10, 12 ), // The special page returns logs whose timestamp < T (not <= T) parseInt( d.substring( 12, 14 ), 10 ) + offset ) ).toISOString(); abuseLogParams.aflstart = d; } api.get( abuseLogParams ) .done( function( data ){ var i, log, filter, period, page, sections = {}; // FIXME: Sort the logs (mainly if query.dir === 'prev') for( i = 0; i < data.query.abuselog.length; i++ ) { log = data.query.abuselog[i]; curLogs[ log.id ] = { filter: log.filter_id, timestamp: log.timestamp }; // YYYY/MM period = log.timestamp.substring( 0, 4 ) + '/' + log.timestamp.substring( 5, 7 ); filter = log.filter_id; page = mw.msg( 'al-page-title', period ); if( sections[ page ] ){ sections[ page ].push( filter ); } else { sections[ page ] = []; } } getSectionsFromPages( sections ); } ); } if ( mw.config.get( 'wgCanonicalSpecialPageName' ) === 'AbuseLog' && mw.config.get( 'wgDBname' ) === 'ptwiki' ) { reDetailsPage = /Especial:Registro_de_abusos\/(\d+)$/; reFilterLink = /^\/wiki\/Especial:Filtro_de_abusos\/(\d+)$/; mw.loader.using( [ 'mediawiki.api', 'mediawiki.Uri' ], function(){ api = new mw.Api(); if ( mw.config.get( 'wgTitle' ) === 'Registro de abusos' ){ $( getPagesToCheck ); } else { revision = mw.config.get( 'wgPageName' ).match( reDetailsPage ); if( revision && revision[1] ){ revision = revision[1]; $( addAbuseFilterStatusLinks ); } } } ); } }( mediaWiki, jQuery ) ); All content in the above text box is licensed under the Creative Commons Attribution-ShareAlike license Version 4 and was originally sourced from https://pt.wikibooks.org/w/index.php?diff=prev&oldid=263296.
![]() ![]() This site is not affiliated with or endorsed in any way by the Wikimedia Foundation or any of its affiliates. In fact, we fucking despise them.
|