Usuário:Danilo.bot/marcas.py

Código

editar
# -*- 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()