Wikipédia:Concursos/I GP Wikimedia Brasil/Avaliação/Script

Origem: Wikipédia, a enciclopédia livre.
# -*- coding: utf-8  -*-
#
#  Script criado por Danilo.mac
#  http://pt.wikipedia.org/wiki/Utilizador:Danilo.mac
 
"""
Utilize os seguntes comandos:
 
-avaliar:PÁGINA              Mostra uma avaliação com base nos parâmeros pré-estabelecidos.
 
-cat:CATEGORIA               Atualiza as marcas dos artigos da categoria.
 
-predef:PREDEFINIÇÃO         Atualiza as marcas dos artigos que possuem essa predefinição.
 
-avaliar                     Faz com que todas as qualidades sejam avaliadas.
                            Note que -avaliar e -avaliar: são dois comandos diferentes
 
-adicionar:TEMA              Adiciona esse tema à marca se ele já não existir. Para mais de um
                            tema use a barra vertical: 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 coloque separe
                            com ";", 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
 
-dry                         Não salva a edição, apenas mostra o diff na tela.

-forçar                      Força a edição do bot, ignorando a data da última avaliação feita
"""
import re, time
import wikipedia as pywikibot
import catlib
from datetime import date
import pagegenerators


problemas = [u'artigo com problemas', u'artigo longo', u'artigo sobre direito com problemas', u'bsre', u'coi', u'caracteres não-padrão',
 u'conflito interwiki', u'contextualizar2', u'conteúdo parcial', u'controverso', u'corrigir', u'ctx2', u'curiosidades', u'direitos-autorais',
 u'disputa-bpv', u'divisão', u'em tradução', u'expandir', u'expandir2', u'fusão', u'fusão com', u'fusão de', u'fusão vot', u'global',
 u'global/brasil', u'global/lusofonia', u'global/portugal', u'hanzi', u'idioma estrangeiro', u'matrad', u'mtag', u'multitag', u'má introdução',
 u'má tradução', u'não informado', u'não informado n', u'não-enc', u'não-enciclopédico', u'não-enciclopédico2', u'parcial', u'parcialcontroverso',
 u'publicidade', u'rec', u'reciclagem', u'reciclar-sobre', u'ren-pag', u'renomear página', u'revisão', u'revisão de tradução', u'revisão-sobre',
 u's-fontes-bpv', u'sem cat', u'sem-fontes-bpv', u'sem-fontes-sobre', u'semimagem-arquitetura', u'semimagem-sobre', u'separar', u'suspeito2',
 u'tradução de', u'vda2', u'wikificação']
bpd = re.compile(u'(?<={{).+?(?=\||\n|}})') # busca predefinições
bp = re.compile(u'(?:^|\n\n|==\n)[^*\n].{100,}?(?=\n\n|\n==)') # busca parágrafos
br = re.compile(u'{{[Rr]efer[eê]ncias|{{[Nn]otas e referências|{{[Rr]ef-?section|{{[Rr]odapé referências|==.*?[Rr]eferências.*?==|{{[Rr]eflist|<references') # busca seção de referências
bl = re.compile(u'\[\[[^:]*?\]\]') # busca ligações internas
bs = re.compile(u'(?s)\n== ?([^=\n}{]+?) ?==(.+?)(?=\n==[^=\n]|$)') # busca seções
bss = re.compile(u'\n===[^=\n]+?===\n') # busca subseções
bref = re.compile(u'<ref[^\n/]*?>.*?</ref>|<ref .+?/>',re.I|re.S) # busca notas de rodapé/referências
brefname = re.compile(u'(?<=<ref name=).+?(?= />|/>| >|>)',re.I)
bi = re.compile(u'\[\[(ficheiro|imagem?|file|arquivo):.*?(\||\]\])|{{imagem dupla\||\| ?(imagem|mapa|mapa_imagem) *=.*?\.[a-z]{3}',re.I) # busca imagens
excecoes = [u'Referências',u'Ver também',u'Notas',u'Notas e referências',u'Discografia',u'Galeria de imagens',
        u'Referências gerais',u'Leitura adicional',u'Subdivisões',u'Leitura recomendada',u'Ligações externas',u'Bibliografia'] #exeções para seções

def avaliar(page):
    try: texto = page.get()
    except pywikibot.IsRedirectPage: texto = page.getRedirectTarget().get()

    if len(texto) < 2000: return (1,u'menos de 2000 bytes')
    predefs = dict([(p.lower(),p) for p in bpd.findall(texto)])
    if u'artigo destacado' in predefs: return (6,u'artigo destacado')
    if u'artigo bom' in predefs: return (5,u'artigo bom')
    ref = br.search(texto)
    if not ref and len(texto) < 8000: return (1,u'menos de 8000 bytes e não tem referências')
    paragrafos = bp.findall(bref.sub('',texto))
    wikilinks = bl.findall(texto)
    if len(wikilinks) < 10: return (1,u'menos de 10 ligações internas')
    subp = filter(lambda x:x.find(u'. ') == -1,paragrafos)
    if len(paragrafos) - (len(subp)/2) < 3: return (1,u'menos de 3 parágrafos')
 
    # Verificando parâmetros para qualidade 3:
    secoes = bs.findall(texto)
    subsec = bss.findall(texto)
    #if len(secoes) + (len(subsec)/5) < 2: return (1,u'menos de 2 seções')
    for predef in [u'mínimo',u'contexto',u'reciclagem',u'reciclar-sobre']:
        if predef in predefs: return (1,u'encontrado [[predefinição:%s]]' % predefs[predef])
    if not ref: return (2,u'não tem seção de referências')
    if len(wikilinks) < 30: return (2,u'menos de 30 ligações internas')
    if len(secoes) + (len(subsec)/5) < 2: return (2,u'menos de 2 seções')
    refs = bref.findall(texto)
    refnames = brefname.findall(texto)
    nrefs = len(refs) - len(refnames) + len(set(refnames))
    if nrefs < 5: return (2,u'menos de 5 referências')
    imagens = bi.findall(texto)
    if len(imagens) < 1: return (2,u'não tem imagem')
    for predef in [u'esboço',u'wikificação',u'revisão',u'revisão-sobre']:
        if predef in predefs: return (2,u'encontrado [[predefinição:%s]]' % predefs[predef])
    if len(paragrafos) - (len(subp)/2) < 5: return (1,u'menos de 5 parágrafos')

    # Verificando parâmetros para qualidade 4:
    if len(texto) < 20000: return (3,u'menos de 20000 bytes')
    if len(wikilinks) < 50: return (3,u'menos de 50 ligações internas')
    if len(secoes) + (len(subsec)/5) < 4: return (3,u'menos de 4 seções')
    if nrefs < 10: return (3,u'menos de 10 referências')
    if len(imagens) < 2: return (3,u'só tem uma imagem')
    for predef in problemas:
        if predef in predefs: return (3,u'encontrado [[predefinição:%s]]' % predefs[predef])
    for s in secoes:
        if s[0] not in excecoes:
            if not bref.search(s[1]) and len(bp.findall(s[1])) > 1:  return (3,u'não foram encontradas referências na seção "%s"' % s[0])
    paragrafos = bp.findall(bref.sub('',texto))
    wkf = [x for x in paragrafos if len(x) > 3504]
    if wkf: return (3,u'parágrafo muito grande (%d bytes): "%s..."' % (len(wkf[0]),wkf[0][0:23]))

    # Nada encontrado:
    return (4,u'indique para [[WP:EAD|EAD]] quando o artigo satisfizer os [[Wikipédia:O que é um artigo bom?|critérios de artigo bom]]')
 
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}]*?)}}?\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',u'5',u'AB',u'6',u'AD']
 
def atualizar(page,q=False,ad=None,ex=u'',imp=[]):
    if page.namespace() == 0: page = page.toggleTalkPage()
    elif page.namespace() != 1: return None
    if page.exists(): texto = page.get()
    else: texto = u''
    marca = bmarca.search(texto)
    if marca: marca = [p for p in marca.group(1).split('|')]
    marcas = [[m[1]]+[m[3]] for m in bmarcas.findall(texto)]
    if not marcas and not marca and not ad and not imp:
        if texto: pywikibot.output(u'Não foram encontradas marcas em '+page.title())
        else: pywikibot.output(page.title()+u' não existe...')
        return None
    elif not marcas and marca and q == -1 and (not [a for a in ad.split(u'|') if a not in marca] or [e for e in ex.split(u'|') if e in marca]):
        pywikibot.output(u'Não foram encontradas marcas para atualizar em '+page.title())
        return None
    if q: q = avaliar(page.toggleTalkPage())
    if marca: qualidade = marca[0]
    elif marcas:
        qmarcas = bqua.findall(str(marcas))
        if qmarcas: qualidade = qmarcas[0]
        else: qualidade = None
    else: qualidade = None
    if qualidade not in qs: qualidade = u'?'
    if q and q[0] > 4:
        qualidade = str(q[0])
        q = False
    nova = u'{{marca de projeto|%s' % qualidade
    rev = None
    if marca and len(marca) > 1:
        for i, p in enumerate(marca):
            if p.startswith(u'rev='):
                rev = p
            elif p.startswith(u'bot='):
                if q and not reav and p[6:] and date(int(p[6:10]),int(p[10:12]),int(p[12:14])).toordinal() - 182 < date.today().toordinal():
                    pywikibot.output(page.title()+u' foi avaliado por robô a menos de 6 meses, não foi reavaliado.')
                    return None
        marca = filter(lambda x:u'=' not in x,marca)
        if len(marca) % 2 == 0: marca.append(u'?')
        for p in marca[1:]: nova += u'|'+p
    if marcas:
        imarcas = [[m[0]]+bimp.findall(m[1]) for m in marcas]
        for m in imarcas:
            if len(m) == 2: nova += u'|'+m[0]+u'|'+m[1]
            else: nova += u'|'+m[0]+u'|?'
    if ad and [e for e in ex.split(u'|') if e in nova.split(u'|')]: ad = None
    elif ad:
        ad = [a for a in ad.split(u'|') if not u'|'+a+u'|' in nova]
        for m in ad: nova += u'|'+m+u'|?'
    if q: nova += u'|bot=%d/{{subst:CURRENTYEAR}}{{subst:CURRENTMONTH}}{{subst:CURRENTDAY2}}' % q[0]
    if not rev:
        rev = brev.search(str(marcas))
        if rev: rev = rev.group(0)
    if rev: nova += u'|'+rev+u'}}\n'
    else: nova += u'|{{subst:rev}}}}\n'
    impsum = {}
    if imp:
        for i in imp:
            if i == 'eimp': continue
            iindex = nova.lower().find(i.strip().lower()+u'|') + len(i) + 1
            if iindex > 20 and nova[iindex] not in imp['eimp']:
                nova = nova[0:iindex] + imp[i].strip() + nova[iindex+1:]
                impsum[i] = imp[i]
    if marcas: texto = bmarcas.sub('',texto)
    if marca: texto = bmarca.sub('',texto)
    if texto.count(u'{{',0,texto.find(u'\n==')) < 3: texto = re.sub(ur'{{[Aa]vançarDiscussão}}\n?',u'',texto)
    texto = re.sub(ur'^({{[Aa]vançarDiscussão}} ?\n?|.*?)',r'\1'+nova,texto)
    if type(q) == tuple:
        if ad: sumario = u'Bot: adicionando marca "%s" e avaliando [[Wikipédia:Qualidade|qualidade]]: %d (%s)' % (ad[0],q[0],q[1])
        else: sumario =  u'Bot: avaliando [[Wikipédia:Qualidade|qualidade]]: %d (%s)' % (q[0],q[1])
    elif ad:
        if marcas: sumario =  u'Bot: adicionando marca "%s" e atualizando marca(s) de wikiprojeto(s)' % ad[0]
        else: sumario =  u'Bot: adicionando marca "%s"' % ad[0]
    elif imp: sumario =  u'Bot: colocando importância em marca(s) de wikiprojeto(s)'
    else: sumario =  u'Bot: atualizando marca(s) de wikiprojeto(s)'
    if impsum:
        for i in impsum: sumario += u', importância %s para %s' % (impsum[i],i)
    if dry:
        if page.exists(): pywikibot.showDiff(page.get(),texto)
        else: pywikibot.output(u'Nova página:\n'+texto)
    else: page.put(texto,comment=sumario)
    return (nova,sumario)
 
dry, reav = False, False
 
def main(*args):
    site = pywikibot.getSite()
    av, predef, cat, subcat, ad, atu , ex, imp, eimp= False, None, None, None, None, None, u'', [], []
    for arg in pywikibot.handleArgs(*args):
        if arg.startswith(u'-predef'):
            predef = arg[8:]
            if not predef: predef = pywikibot.input(u'Qual predefinição?')
            if predef:
                if predef.find(u':') != -1: predef = pywikibot.Page(site,predef)
                else: predef = pywikibot.Page(site,u'Predefinição:'+predef)
        elif arg == u'-avaliar':
            av = True
        elif arg.startswith(u'-adicionar:'):
            ad = arg[11:]
        elif arg.startswith(u'-avaliar:'):
            qualidade = avaliar(pywikibot.Page(site,arg[9:]))
            pywikibot.output(u'qualidade %d (%s)' % (qualidade[0],qualidade[1]))
            return
        elif arg.startswith(u'-cat'):
            cat = arg[5:]
            if not cat: cat = pywikibot.input(u'Qual categoria?')
            cat = catlib.Category(site,cat)
        elif arg.startswith(u'-subcat'):
            subcat = arg[8:]
            if not subcat: subcat = pywikibot.input(u'Qual categoria?')
            subcat = catlib.Category(site,subcat)
        elif arg.startswith(u'-atualizar:'):
            atu = arg[11:]
            if not atu: atu = pywikibot.input(u'Qual artigo?')
            if atu: atu = pywikibot.Page(site,atu)
        elif arg.startswith(u'-exceção:'):
            ex = arg[9:]
        elif arg.startswith(u'-imp:'):
            imp = dict([i.split(u':') for i in arg[5:].split(u';')])
        elif arg.startswith(u'-eimp:'):
            eimp = arg[6:].split(u',')
        elif arg.startswith(u'-dry'):
            global dry
            dry = True
        elif arg.startswith(u'-forçar'):
            global reav
            reav = True
        elif arg.startswith('-file'):
            if len(arg) == len('-file'):
                fileName = pywikibot.input(
                    u'Enter name of file:')
            else:
                fileName = arg[len('-file:'):]
    if not cat and not subcat and not atu and not predef and not fileName: cat = pywikibot.input(u'Qual categoria?')
    if imp: imp['eimp'] = eimp
    if cat or subcat:
        if subcat:
            cat = subcat
            subcat = 1
        for page in cat.articles(subcat):
            if not page.namespace() in [0,1]: continue
            novo = atualizar(page,av,ad,ex,imp)
            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])
    elif atu:
        novo = atualizar(atu,av,ad,ex,imp)
        if novo: pywikibot.output(atu.title()+u' -> '+novo[1])
    elif predef:
        for page in predef.getReferences(onlyTemplateInclusion=True):
            if not page.namespace() is 1: continue
            novo = atualizar(page,av,ad,ex,imp)
            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])
    elif fileName:
        gen = pagegenerators.TextfilePageGenerator(fileName)
        gen = pagegenerators.NamespaceFilterPageGenerator(gen,[0])
        preloadingGen = pagegenerators.PreloadingGenerator(gen, pageNumber = 50)
        for page in preloadingGen:
	    try:
              novo = atualizar(page,av,ad,ex,imp)
              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])

	    except pywikibot.IsRedirectPage:
              pywikibot.output('\03{lightred}--> %s e um redirect\03{default}' % page)
              continue
 
	    except pywikibot.NoPage:
              pywikibot.output('\03{lightred}--> %s não existe\03{default}' % page)
              continue
	     
	    except pywikibot.BadTitle:
              pywikibot.output('\03{lightred}--> %s titulo nao aceite\03{default}' % page)
              continue
 
	    except pywikibot.PageNotFound:
              pywikibot.output('\03{lightred}--> %s não existe\03{default}' % page)
              continue

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