Usuário:Danilo.bot/marcas.py

Origem: Wikipédia, a enciclopédia livre.
Documentação

Descrição

Script para atualização de marcas de projeto.

Uso

O código deve ser salvo na pasta /script da versão core do pywikibot. Para usá-lo deve estar na pasta anterior (pasta raiz do pywikibot) e digitar no console (Linux) ou DOS (Windows) "python pwb.py marcas parâmetros".

O script faz as seguintes atualizações:

  • Se houver marcas antigas na página de discussão ele coloca na marca nova. Essa atualização é feita independente dos parâmetros passados ao script.
  • Adiciona temas se ainda não existir na marca nova ou em uma antiga. Use o parâmetro -adicionar:"tema1, tema2".
  • Remove temas. Use o parâmetro -remover:"tema1, tema2".
  • Adiciona importância a um tema. Use o parâmetro -imp:"tema1:importância, tema2:importância" e para exceções (ex: não adicionar 3 se já tiver importância 4) use -eimp:importância,importância.
  • Remove o parâmetro |bot= da marca se houver. Isso só é feito automaticamente quando é feita uma das alterações acima ou quando é usado o parâmetro -rmbot para forçar a remoção quando nenhuma outra alteração é feita.
  • Remove o parâmetro rev quando não existe avaliação humana. Isso só é feito automaticamente quando é feita uma das alterações acima.

Geradores

O script aceita todos geradores do pagegenerators, com duas mudanças:

  • As páginas são automaticamente convertidas para páginas de discussão, então mesmo se o gerador listar artigos o script irá verificar as discussões dos artigos.
  • Apenas páginas do domínio Discussão e Anexo Discussão são verificadas, então serão desconsideradas as páginas que não estiverem nesses dois domínios ou nos respectivos domínios de conteúdo.

Exemplos de utilização

Atualiza todas as marcas antigas nas páginas que trancluem a Predefinição:Capital/Marca:

python pwb.py marcas -transcludes:"Predefinição:Capital/Marca"

Adiciona o tema Física na marca na Discussão:Teorema de Norton e faz outras correções aplicáveis:

python pwb.py marcas -page:"Teorema de Norton" -adicionar:Física

Remove o parâmetro |bot= na marca na Discussão:Alumínio mesmo se não houver outra alteração a ser feita:

python pwb.py marcas -page:"Alumínio" -rmbot

Ver também

Código[editar | editar código-fonte]

# -*- coding: utf-8  -*-
"""
@ Autor: [[Usuário:Danilo.mac]]
@ Licença de software: GNU General Public License 2.0 (GPLv2) e Creative Commons Attribution/Share-Alike (CC-BY-SA)

Utilize os seguntes comandos:

-adicionar:TEMA         Adiciona esse tema à marca se ele já não existir. Para mais de um
                        tema use vírgula: TEMA1,TEMA2

-remover:TEMA           Remove esse tema se tiver na marca. Para mais de um tema use
                        vírgula: TEMA1,TEMA2

-exceção:TEMA           Só adiciona o tema se TEMA não estiver na marca.

-imp:TEMA:I             Adiciona importância I para TEMA. Para mais de um tema separe
                        com vírgula, exemplo: -imp:TEMA1:2,TEMA2:3

-eimp:I                 Só adiciona a importância se a importância já não for I. Para mais
                        exceções separe com vírgula, exemplo: -eimp:3,4

-simular                Não salva a edição, apenas mostra o diff na tela.

-rmbot                  Força a remoção do parâmetro |bot= mesmo quando não existe outra
                        alteração a fazer. Sem o -rmbot o parâmetro bot é removido desde que
                        haja outra alteração a fazer.

-- Comandos para especificar as páginas que serão trabalhadas --

Este script utiliza a classe GeneratorFactory para especificar as páginas, veja a documentação
com a lista completa dos comandos no arquivo pagegenerators.py ou utilize o comando abaixo:

-comandos               Exibe na tela todos os comandos disponíveis para especificar as páginas
"""

import re
from collections import OrderedDict
import pywikibot
from pywikibot import pagegenerators

bmarca = re.compile(u'{{ *[Mm]arca de projeto *\|?([^\n}]*?)}}') #busca a marca
bmarcas = re.compile(u'{{ *(?:Predefinição:)?([Cc]lassificação/)? *(([Áá]lbuns)|[^\n\|}/]+?)(?(1)[|}]|(?(3)[|}]|/[Mm]arca))\|?([^}]*?)}}?\n?') # busca marcas antigas
bqua = re.compile(u'qualidade *= *0?(\d|A[BD])')
bimp = re.compile(u'importância *= *0?(\d)')
brev = re.compile(u'rev *= *\d{8}')
qs = {u'1', u'2', u'3', u'4'}
predefs = {u'Projeto-Pokémon': u'Pokémon', u'Wikipédia:PTV/Marca': u'Televisão', u'Anti-Vandalismo': u'Antivandalismo', u'catolicismo_diálogo': u'Catolicismo',
  u'Wikipedia:Projetos/Ferrovipédia/ArtigoMembro': u'Ferrovipédia', u'Países/ArtigoMembro': u'Países', u'Wikipedia:Projetos/Televisão/Marca': u'Televisão',
  u'Wikipedia:Projetos/Harry Potter/Marca': u'Harry Potter', u'Wikipedia:Projetos/Cidades do Mundo/Portugal/Marca': u'Localidades de Portugal',
  u'ProjetoLGBT': u'LGBT',  u'projetobd': u'Banda Desenhada', u'Canções': u'Canções', u'canções': u'Canções', u'Wikipedia:Projetos/Cinema/Marca': u'Cinema',
  u'Wikipédia:Projetos/Subdivisões do Brasil/Artigo membro': u'Subdivisões do Brasil', u'Wikipedia:Projetos/Cidades do Mundo/Dinamarca/marca': u'Dinamarca', 
  u'WikiProjecto Escolares e universitários': u'Escolares e universitários', u'Wikipedia:Projetos/Cidades do Mundo/Espanha/Marca': u'Espanha', 
  u'WikiProjecto Discografias': u'Discografias', u'Projetobd': u'Banda Desenhada', u'álbuns': u'Álbuns', u'Música/Marca': u'Música', u'Ferrovipédia/Marca': u'Ferrovipédia', u'Cinema/Marca': u'Cinema', u'Games/Marca': u'Games'}
bmarcas2 = re.compile(u'{{ *(?:Predefinição:)? *(%s)\|?([^}]*?)}}?\n?' % u'|'.join(p for p in predefs)) # busca marcas antigas fora de padrão
stemas = {u'Filme': u'Cinema', u'Empresa': u'Empresas', u'Biografia': u'Biografias', u'Político': u'Políticos', u'Capital': u'Capitais',
  u'Hisória e sociedade': u'História', u'Telenovela': u'Telenovelas', u'Freguesias de Portugal': u'Localidades de Portugal'}

def atualizar(page, adicionar=[], remover=[], excecoes=[], imp={}, eximp=[], rmbot=False):
  if page.namespace() not in {1, 103}:
    return None
  try:
    texto = page.get()
  except pywikibot.NoPage:
    texto = u''
  rev = None
  bot = False
  adtema = []
  rmtema = []
  temas = OrderedDict()
  qualidade = None

  # Marca nova
  marca = bmarca.search(texto)
  if marca: # Tem marca nova
    marca = [p for p in marca.group(1).split('|')]
    tema = None
    n = 1
    if len(marca) > 1: # Tem marca nova e ela tem parâmetros
      for param in marca:
        if param.startswith(u'rev='): # Tem |rev= na marca
          rev = param
        elif param.startswith(u'bot='): # Tem parâmetro |bot=
          bot = param
        elif u'=' not in param: # Não tem "=" no parâmetro
          if n == 1: # Primeiro parâmetro é a qualidade
            qualidade = param
          elif n % 2 == 0: # Parâmetro par é tema
            tema = param
          else: # Parâmetro impar é importância
            temas[tema in stemas and stemas[tema] or tema] = param or u'?'
            tema = None
          n += 1
      if tema: # Último tema não tem importância
        temas[tema] = u'?'
  rmbot = rmbot and bot # Só considera que vai remover o |bot= se tiver
  # Marcas antigas
  marcas = [(m[1], m[3]) for m in bmarcas.findall(texto)] + [(predefs[m[0]], m[1]) for m in bmarcas2.findall(texto)]
  if marcas: # Tem marcas antigas
    imarcas = [[m[0]] + bimp.findall(m[1]) for m in marcas] # Importâncias nas marcas antigas
    for m in imarcas: # Pega os parâmetros das marcas antigas
      if m[0] in temas and temas[m[0]] != u'?':
	continue # Importância definida na marca nova tem prioridade
      elif len(m) == 2:
        temas[m[0] in stemas and stemas[m[0]] or m[0]] = m[1]
      else:
        temas[m[0] in stemas and stemas[m[0]] or m[0]] = u'?'
    if not rev: # Não tem rev na marcas novas
      rev = brev.search(str(marcas)) # Busca rev nas antigas
      rev = rev and rev.group(0)
    if not qualidade: # Não tem qualidade na marca nova
      qmarcas = bqua.search(str(marcas)) # Busca qualidade em marcas antigas
      if qmarcas:
        qualidade = qmarcas.group(1)
  qualidade = qualidade in qs and qualidade or u'?'
  if not rev and qualidade and qualidade != u'?':
    # Buscar no histórico
    history = page.fullVersionHistory()
    marcaSemData = bmarca.search(texto)
    if not marcaSemData:
      marcaSemData = re.compile(u'qualidade *= *' + qualidade).search(texto)
    if marcaSemData:
      marcaSemData = marcaSemData.group(0)
      revision = history[0]
      for r in history:
        if marcaSemData in r[3]:
          revision = r
        else:
          break
      rev = u'rev=' + revision[1].totimestampformat()[0:8]
  if rev and qualidade == u'?':
    rev = None # Só mantém rev se tiver avaliação humana
  # Adição de temas
  if not set(excecoes) & set(temas):
    for ad in adicionar:
      if ad not in temas:
        temas[ad] = u'?'
        adtema.append(ad)
  # Remoção de temas
  for rm in remover:
    if rm in temas:
      del temas[rm]
      rmtema.append(rm)
  # Adição de importância
  imp = dict((tema, i) for tema, i in imp.items() if tema in temas and temas[tema] not in [i] + eximp)
  for tema in imp:
    temas[tema] = imp[tema]
  # Substituição de temas
  temas = [(t in stemas and stemas[t] or t, i) for t, i in temas.items()]

  # Verificações:
  # Não tem marca antiga ou nova nem vai adicionar
  if not marcas and not marca and not adtema:
    if texto:
      pywikibot.output(u'Não foram encontradas marcas em ' + page.title())
    else:
      pywikibot.output(page.title() + u' não existe...')
    return None
  # Não tem marca antiga e ( (tem nova mas não adicionar ou remover tema ou remover bot) ou (não tem marca nova e não vai adicionar) )
  elif not marcas and ((marca and not adtema and not rmtema and not imp and not rmbot) or (not marca and not adtema)):
    pywikibot.output(u'Não foram encontradas marcas para atualizar em ' + page.title())
    return None

  # Monta a nova marca
  imps = {'1', '2', '3', '4'}
  nova = u'{{Marca de projeto|' + qualidade + (rev and u'|' + rev or u'') + u'|' + u'|'.join(t + u'|' + (i in imps and i or u'?') for t, i in temas) + u'}}\n'

  # Substitui marcas no texto
  if marcas: # Remove marcas antigas da página
    texto = bmarcas.sub('', bmarcas2.sub('', texto))
  if marca: # Remove marcas novas da página
    texto = bmarca.sub('', texto)
  if texto.count(u'{{', 0, texto.find(u'\n==')) < 3: # Tem menos de 3 predefinições antes da primeira seção
    texto = re.sub(ur'{{[Aa]vançarDiscussão}}\n?', u'', texto) # Remove {{avanção discussão}} se tiver
  texto = re.sub(ur'^({{[Aa]vançarDiscussão}} ?\n?|.*?)', r'\1' + nova, texto) # Adiciona a marca no inicio ou depois de {{avançar discussão}}

  # Sumário da edição
  sumario = []
  if rmtema:
    sumario.append(u'removendo marca{} {}'.format(len(rmtema) > 1 and u's' or u'', listar(rmtema)))
  if adtema:
    sumario.append(u'adicioando marca{} {}'.format(len(adtema) > 1 and u's' or u'', listar(adtema)))
  if marcas:
    sumario.append(u'[[WP:Projetos/Padronização/Marcas|atualizando marca{}]]'.format(len(marcas) > 1 and u's' or u''))
  if imp:
    sumario.append(u'colocando importância em marca{}: {}'.format(len(imp) > 1 and u's' or u'',
      listar([u'{} para {}'.format(i, tema) for tema, i in imp.items()])))
  if sumario:
    sumario = u'Robô: ' + listar(sumario)
  else:
    sumario =  u'Robô: atualizando marca{0} de wikiprojeto{0}'.format(len(temas) > 1 and u's' or u'')

  if simular: # Com o parâmetro -simular não salva
    if page.exists():
      pywikibot.showDiff(page.get(), texto)
    else:
      pywikibot.output(u'Nova página:\n' + texto)
  else: # Salva o texto
    try:
      page.put(texto, comment=sumario)
    except pywikibot.LockedPage:
        pywikibot.output(u'\03{lightred}' + page.title() + u'está protegida!\03{default}')
        return
  return (nova, sumario)

def listar(itens):
  lista = u''
  n = len(itens) > 1 and len(itens) - 1 or 1
  for i, item in enumerate(itens):
    lista += (i == n and u' e ' or i > 0 and u', ' or u'') + item
  return lista

simular, reav = False, False

def main(*args):
  site = pywikibot.getSite()
  params = {}
  genFactory = pagegenerators.GeneratorFactory()
  limit = 0
  for arg in pywikibot.handleArgs(*args):
    if arg.startswith(u'-avaliar'):
      pywikibot.output(u'A qualidade não é mais avaliada por robô na Wikipédia')
      return
    elif arg.startswith(u'-adicionar:'):
      params['adicionar'] = [a.strip() for a in arg[11:].split(u',')]
    elif arg.startswith(u'-remover:'):
      params['remover'] = [a.strip() for a in arg[9:].split(u',')]
    elif arg.startswith(u'-exceção:'):
      params['excecoes'] = [e.strip() for e in arg[9:].split(u':')]
    elif arg.startswith(u'-imp:'):
      params['imp'] = dict([i.strip().split(u':', 1) for i in arg[5:].split(u',')])
    elif arg.startswith(u'-eimp:'):
      params['eimp'] = arg[6:].split(u',')
    elif arg.startswith(u'-rmbot'):
      params['rmbot'] = True
    elif arg.startswith(u'-simular'):
      global simular
      simular = True
      limit = int(arg[8:] or 0)
    elif arg == u'-comandos':
      pywikibot.output(pagegenerators.parameterHelp)
      return
    elif not genFactory.handleArg(arg):
      pywikibot.output(u'#Comando não encontrado: '+ arg)
      return
  def gen():
    for page in genFactory.getCombinedGenerator():
      if page.namespace() % 2 == 0:
        page = page.toggleTalkPage()
      if page.namespace() in {1, 103}:
        yield page
      else:
        pywikibot.output(u'Página [[{}]] não verificada (domínio não previsto para a colocação de marcas)'.format(page.title()))
  for count, page in enumerate(pagegenerators.PreloadingGenerator(gen())):
    novo = atualizar(page, **params)
    t = page.title()
    t = t[0:t.find(u':') + 1] + u'\03{lightblue}' + t[t.find(u':') + 1:] + u'\03{default}' # Cor
    if novo:
      pywikibot.output(t + u' -> ' + novo[1])
    if limit and count + 1 == limit:
      break


if __name__ == "__main__":
  try: main()
  finally: pywikibot.stopme()