Usuario:Bigsus-bot/RevisarPlantillasTemporales.py

Este script programado en python se utiliza para retirar las plantillas {{en desarrollo}} y {{traducción}} abandonadas.

Para ejecutarlo se requiere la librería pywikipedia.

#!/usr/bin/python
# -*- coding: utf-8  -*-
#codigo GPL, autor: BigSus
#Este código revisa la inclusión de varias plantillas, retirándolas si el usuario que la introdujo lleva cierto tiempo sin editar en el artículo

import wikipedia, userlib
import replace, pagegenerators
import re
import time
import datetime
from datetime import datetime, date, timedelta

#Para ver progreso
#templatecount.py -count "en desarrollo" "endesarrollo" "en obras" "enobras" "traducción" "en uso"

#Habrá que pensar algo para revisar la plantilla evento actual

modo = None

parametros = {
        'traduccion': {
            'patron': ur'([Tt]raducci[oó]n)',
            'nombreplantilla': u'traducción',
            'diaspermitidos': 45,
            'resumen': u'Bot: Retirando plantilla "[[Plantilla:Traducción|traducción]]".',
            },
        'desarrollo': {
            'patron': ur'([Ee]n[_ ]?desarrollo|[Ee]n[_ ]?obras)',
            'nombreplantilla': u'en desarrollo',
            'diaspermitidos': 30,
            'resumen': u'Bot: [[Usuario:Bigsus-bot/Tarea/7|Retirando plantilla]] "[[Plantilla:En desarrollo|en desarrollo]]".',
            },
        'uso': {
            'patron': ur'([Ee]n[_ ]?uso)',
            'nombreplantilla': u'en uso',
            'diaspermitidos': 10,
            'resumen': u'Bot: Retirando plantilla "[[Plantilla:En uso|en uso]]".',
            },
        'eventoactual': {
            'patron': ur'([Ee]vento[_ ]?actual|[Aa]ctualidad|EA)',
            'nombreplantilla': u'evento actual',
            'diaspermitidos': 90,
            'resumen': u'Bot: Retirando plantilla "[[Plantilla:Evento actual|evento actual]]".',
            },
}

def getPatron():
    return ur' *\{\{ *'+parametros[modo]['patron']+ur'(?: *\| *[^\}]+)? *\}\} *\n?'

def buscarEdicionMarcadaConPlantilla(pagina):
    i=None
    ediciones = pagina.getVersionHistory()
    plantillaR = re.compile(getPatron())
    versionmarcada = None
    for edicion in ediciones:
        try:
            wikipedia.output(u'Revisando edición de %s de fecha %s' % (edicion[2].encode('ascii','replace'),edicion[1]))
            contenido=pagina.getOldVersion(edicion[0])
            if len(plantillaR.findall(contenido))==0: #Si no se encuentra reviso en las siguientes versiones            
                if i==None:
                    i=0
                elif i>4:
                    break
                else:
                    i+=1
            else:
                i=None
                versionmarcada=edicion
	    #print i,versionmarcada
        except:
            wikipedia.output(u'No se ha podido revisar el contenido de esta revisión. Tal vez sea una redirección')
    return versionmarcada

def esRevisable(pagina):
  try:
    contenidoOriginal=pagina.get()
    nombresEvitarR = re.compile(u'Plantilla:')
    plantillaR = re.compile(getPatron())
    patronNowiki=ur'<nowiki> *%s *</nowiki>' % getPatron()
    nowikiR = re.compile(patronNowiki)
    if len(nombresEvitarR.findall(pagina.title()))>0: #Evito modificar plantillas
        wikipedia.output(u'Es una plantilla. No la reviso.')
        return False
    elif len(nowikiR.findall(contenidoOriginal))>0: #Sustituyo <nowiki>XX</nowiki> por {{tl|XX}}
        contenido=contenidoOriginal        
        #Busco recursivamente por si en el artículo existen varias coincidencias
        nuevoContenido = hacerRemplazo(contenido,patronNowiki,u'{{tl|%s}}' % (parametros[modo]['nombreplantilla'])) #transclude
        while nuevoContenido!=contenido:
            contenido = nuevoContenido
            nuevoContenido = hacerRemplazo(contenido,patronNowiki,u'{{tl|%s}}' % (parametros[modo]['nombreplantilla']))
        wikipedia.showDiff(contenidoOriginal, nuevoContenido)
        pagina.put(nuevoContenido, u'Sustituyo nowiki por tl para que no enlace desde la plantilla en %s' % (modo))
        return True
    elif len(plantillaR.findall(contenidoOriginal))==0:
        wikipedia.output(u'Solo enlaza a la plantilla, no la muestra')
        return False
    else:
        return True
  except wikipedia.IsRedirectPage:
    return False

def ultimasEdiciones(pagina, usuario):
    ultimaEdicion=None
    ultimaEdicionUsuario=None
    ediciones = pagina.getVersionHistory(False,False,True)

    for edicion in ediciones:
        if ultimaEdicion==None:
            ultimaEdicion=edicion[1]
        if edicion[2]==usuario and ultimaEdicionUsuario==None:
            ultimaEdicionUsuario=edicion[1]
    wikipedia.output('EdicionUsuario: %s' % (usuario))
    return convertirAdatetime(ultimaEdicion), convertirAdatetime(ultimaEdicionUsuario)

def ultimaEdicionMenos5Dias(pagina):
    ultimaEdicion=pagina.getVersionHistory(False,False,True)[0][1]
    return date.today() - convertirAdatetime(ultimaEdicion).date() <= timedelta(days=5)

def convertirAdatetime(cadenaFecha):
    return datetime.strptime(cadenaFecha,u"%Y-%m-%dT%H:%M:%SZ")

def hacerRemplazo(texto,patronAplicado,remplazo):
    plantillaR = re.compile(patronAplicado)
    return plantillaR.sub(remplazo, texto)

def retirarPlantilla(pagina,resumen):
    contenidoOriginal = pagina.get(True) #Fuerzo a traer la última versión
    contenido=contenidoOriginal

    #Busco recursivamente por si en el artículo existen varias secciones marcadas con plantilla
    while True:
        #Para evitar plantillas dentro de plantillas cambio las embebidas por palabra clave y las restituyo tras aplicar el patrón.
        nuevoContenido = hacerRemplazo(contenido,ur'({{[^}]*?){{',ur'\1@RETIRARINI@')
        nuevoContenido = hacerRemplazo(nuevoContenido,ur'(@RETIRARINI@[^{]*?)}}',ur'\1@RETIRARFIN@')
        nuevoContenido = hacerRemplazo(nuevoContenido,getPatron(),'')
        nuevoContenido = hacerRemplazo(nuevoContenido,ur'@RETIRARINI@','{{')
        nuevoContenido = hacerRemplazo(nuevoContenido,ur'@RETIRARFIN@','}}')
        if nuevoContenido==contenido:
            break
        else:
            contenido = nuevoContenido

    wikipedia.showDiff(contenidoOriginal, nuevoContenido)
    wikipedia.output(resumen)
    pagina.put(nuevoContenido, resumen)

def revisarPagina(pagina):
    versionmarcada = buscarEdicionMarcadaConPlantilla(pagina)
    print versionmarcada
    if versionmarcada != None:
        ultimaEdicion,ultimaEdicionUsuario = ultimasEdiciones(pagina,versionmarcada[2])
        hoy = date.today()

        #Si la última intervención de quien insertó la plantilla es mayor a X días y la última edición de cualquiera es mayor a 5 días
        if hoy - ultimaEdicionUsuario.date() > timedelta(days=parametros[modo]['diaspermitidos']) and hoy - ultimaEdicion.date() > timedelta(days=5):
            wikipedia.output(u'Página: %s Usuario: %s Edición marcada: %s Última edición usuario: %s Ultima edición general: %s' % (pagina.title(),versionmarcada[2],versionmarcada[1],ultimaEdicionUsuario,ultimaEdicion))
            wikipedia.output(u'Página: %s Retirar. La plantilla fue insertada por %s el %s. La última edición de este usuario fue el %s y la última general el %s' % (pagina.title(),versionmarcada[2],convertirAdatetime(versionmarcada[1]).strftime('%d de %B de %Y'),ultimaEdicionUsuario,ultimaEdicion))
            resumen = u'%s Fue insertada por [[Usuario:%s]] el %s y su última edición en él fue el %s.' % (parametros[modo]['resumen'], versionmarcada[2].encode('ascii','replace'),convertirAdatetime(versionmarcada[1]).strftime('%d de %B de %Y'),ultimaEdicionUsuario.strftime('%d de %B de %Y'))
            retirarPlantilla(pagina, resumen)
            if modo==u'traduccion':
                avisoUsuario(versionmarcada[2], u'Colaboración en artículo [[%s]]' % (pagina.title()), u'Se ha retirado la plantilla traducción que colocó en el artículo el %s, ya que ha transcurrido bastante tiempo desde que colaboró en él por última vez (el %s).\nSi dejó partes sin traducir revise si es necesario hacer limpieza. ' % (convertirAdatetime(versionmarcada[1]).strftime('%d de %B de %Y'),ultimaEdicionUsuario.strftime('%d de %B de %Y')) )
        else:
            wikipedia.output(u'Página: %s Conservar. La plantilla fue insertada por %s el %s. La última edición de este usuario fue el %s y la última general el %s' % (pagina.title(),versionmarcada[2],convertirAdatetime(versionmarcada[1]).strftime('%d de %B de %Y'),ultimaEdicionUsuario,ultimaEdicion))

def avisoUsuario(usuario, titulo, mensaje):
    site = wikipedia.Site("es", "wikipedia")
    discusionUsuario = userlib.User(site, usuario).getUserTalkPage()
    discusionUsuario.get()
    discusionUsuario.put(u"%s\n\n== %s ==\n\n%s ~~~~" % (discusionUsuario.get(),titulo,mensaje), u'Avisando sobre retirada de plantilla', minorEdit=False)

def logErrores(error):
    site = wikipedia.Site("es", "wikipedia")
    pageLog = wikipedia.Page(site, "Usuario:Bigsus-bot/Log")
    pageLog.put("%s\n\n%s - %s" % (pageLog.get(),datetime.now().strftime("%d/%m/%Y %H:%M:%S"),error), u'Anotando error en log')

def main(titulo=None):
    site = wikipedia.Site("es", "wikipedia")

    if titulo==None:
        referredPage = wikipedia.Page(site, u"Plantilla:%s" % (parametros[modo]['nombreplantilla']))
        #Páginas que apuntan a la plantilla siguiendo redirecciones
        gen = pagegenerators.ReferringPageGenerator(referredPage,True)
        for pagina in gen:
          try:
            wikipedia.output(u'>Procesando página %s . . .' % (pagina.title()))
            if pagina.namespace()==0 or pagina.namespace()==104: #Solo trabajo en espacio principal y anexo
                if not ultimaEdicionMenos5Dias(pagina):
                    #Revisar si se encuentra entre nowikis o noincludes. Evitar la documentación de la propia plantilla
                    if esRevisable(pagina):
                        revisarPagina(pagina)
                else:
                    wikipedia.output(u'El artículo ha sido modificado recientemente')
          except:
            wikipedia.output('Error procesando página %s' % (pagina))
            #logErrores(u'Error revisando retirada de plantilla en página %s' % (pagina.title()))
    else:
        pagina = wikipedia.Page(site, titulo)
        try:
            wikipedia.output(u'>Procesando página %s . . .' % (pagina.title()))
            if not ultimaEdicionMenos5Dias(pagina):
                if esRevisable(pagina):
                    revisarPagina(pagina)
            else:
                wikipedia.output(u'El artículo ha sido modificado recientemente')
        except:
            wikipedia.output('Error procesando página %s' % (pagina))
            logErrores(u'Error revisando retirada %s en página %s' % (parametros[modo]['nombreplantilla'],pagina.title()))

for arg in wikipedia.handleArgs():
    if arg.startswith('-modo:'):
        modo=arg[6:]

if modo==None:
    pregunta = wikipedia.inputChoice(u'Indique en que modo iniciar el script:', ['desarrollo', 'traduccion', 'uso', 'eventoactual'], ['D', 'T', 'U', 'A'], 'D')
    if pregunta=='d' or pregunta=='D':
        modo = 'desarrollo'
    elif pregunta=='t' or pregunta=='T':
        modo = 'traduccion'
    elif pregunta=='u' or pregunta=='U':
        modo = 'uso'
    elif pregunta=='a' or pregunta=='A':
        modo = 'eventoactual'

wikipedia.output(u'Ejecutando en modo: %s' % (modo))
main()

"""
site = wikipedia.Site("es", "wikipedia")
pagina = wikipedia.Page(site, u"Usuario:Bigsus/Pruebas")
modo = 'traduccion'
retirarPlantilla(pagina,'')
"""