actualizar · discusión · código desprotegido
Información de fichero
|
{{Recordatorio CAD}}
, Wikipedia:Candidatos a artículos destacados/Número y Wikipedia:Candidatos a artículos destacados, originalmente de EmBOTellado (disc. · contr. · bloq.). Actualmente actualizada por ChessBOT (disc. · contr. · bloq.) y TronaBot (disc. · contr. · bloq.), y previamente por SebrevBOT (disc. · contr. · bloq.), AstaBOTh15 (disc. · contr. · bloq.), SamuraiBot (disc. · contr. · bloq.), Botito777 (disc. · contr. · bloq.), BOTzilla (disc. · contr. · bloq.), Gizbot (disc. · contr. · bloq.) y Fidelbotquegua (disc. · contr. · bloq.). A notar la reestructuración y mejora del script por Coet (disc. · contr. · bloq.).# -*- coding: utf-8 -*-
import locale, os, re, sys
from datetime import datetime, timedelta
sys.path.append("/shared/pywikipedia/core")
from pywikibot import Category, Site, output, Page, showDiff as show_diff
from pywikibot import handleArgs as handle_args, NoPage
from pywikibot.data import api
class Templates(object):
"""Este objeto extrae todas las plantillas de un artículo con cada parámetro por medio
del pywikibot.
Hay un bug cuando se trata de obtener los parámetros de plantillas con \n| (29-07-2014).
"""
def __init__(self, source):
self._source = source
def templates_with_params(self):
self._templates = [(o[0].title(withNamespace=False), ["=" in p and (p.split("=",1)[0].strip(), p.split("=",1)[1].strip()) or (o[1].index(p), p.strip()) for p in o[1]]) for o in self._source.templatesWithParams()]
return self._templates
def has_template(self, tname):
"""Devuelve el número de veces que aparece una plantilla."""
tname = capitalize(tname)
if not hasattr(self, "_templates"):
self.templates_with_params()
c=0
for template, params in self._templates:
if template == tname:
c+=1
return c
def get_template_param(self, tname, param):
"""Devuelve totas las plantillas 'tname' con el parámetro 'param'"""
tname = capitalize(tname)
if not hasattr(self, "_templates"):
self.templates_with_params()
templates=[]
if isinstance(param, int):
param = param-1
for template, params in self._templates:
if template == tname:
if not isinstance(param, basestring):
if len(params)-1 <= param:
templates.append((template, params[param][1]))
else:
for items in params:
if items[0] == param:
templates.append((template, items[1]))
return templates
class Usuario(object):
def __init__(self, nick):
self.nick = nick
params = {
"action": "query",
"list": "users",
"ususers": nick,
"usprop": "groups",
}
q = api.Request(site, **params)
self.data = q.submit()
@property
def is_bot(self):
if self.is_anon: return False
if self.data['query'].has_key('users'):
if self.data['query']['users'][0].has_key('groups'):
user = self.data["query"]["users"][0]
return "bot" not in user['groups']
else:
output(u"Ha sido imposible obtener grupos de usuario para %s" % self.data['query']['users'][0]['name'])
@property
def is_anon(self):
return self.data["query"]["users"][0].has_key("invalid")
class Candidato_CAD(object):
u"""Este objeto obtiene los datos de cada artículo candidato."""
def __init__(self, articulo):
self._articulo = articulo
self._pagina = Page(site, u"Wikipedia:Candidatos a artículos destacados/%s" % articulo)
self._contenido = self._pagina.text
self._primera_edicion = self._pagina.oldest_revision #revid, user, timestamp, comment
self._ultima_edicion = self._pagina.latest_revision
self._primera_fecha = self._pagina.oldest_revision.timestamp
self._ultima_fecha = self._pagina.latest_revision.timestamp
def participacion(self):
"""Determina el grado de participación."""
diferencia_fecha = self._ultima_fecha - self._primera_fecha
dias_sin_participar = datetime.today() - self._ultima_fecha
#si lleva al menos un día abierta pero sin editarse nada
if (self._primera_edicion == self._ultima_edicion) and (dias_sin_participar > timedelta(days=1)):
return 0
#si se ha llegado a publicar pero sin más ediciones, o ya pasan tres días desde la última edición
elif (self._primera_fecha != self._ultima_fecha) or (diferencia_fecha > timedelta(days=3)):
if dias_sin_participar > timedelta(days=3):
return 0
elif dias_sin_participar <= timedelta(days=2):
return 2
#obviously dias_sin_participar == 3
else:
return 1
elif self._primera_fecha == self._ultima_fecha == datetime.today():
return ""
return ""
def participantes(self):
"""Obtiene el número de participantes en la sección Opiniones"""
usuarios = set()
for edicion in self._pagina.revisions():
#if edicion.anon: continue
if edicion.minor: continue
elif Usuario(edicion.user).is_bot: continue
usuarios.add(edicion.user)
return len(usuarios)
def observaciones(self):
"""Determina el valor de la columna 'observaciones'."""
if re.search("(?<!<s>)\{\{Cierre ACAD.*\}\}", self._contenido):
return "24h"
if (self._primera_fecha == self._ultima_fecha) or ((self._ultima_fecha - self._primera_fecha) <= timedelta(days=3)):
return "Nueva"
elif (datetime.today() - self._ultima_fecha) > timedelta(days=3):
return "Emergencia"
return ""
def datos(self):
"""Obtenemos los siguientes datos: artículo, proponente, mes, tamaño, votos pro, votos contra y fecha cierre"""
locale.setlocale(locale.LC_ALL, sys.platform.startswith("win") and "Spanish_Spain" or "es_ES.UTF8")
#Por defecto (en caso de no poder extraer el proponente expuesto), el proponente
#será el creador de la candidatura.
proponente = self._primera_edicion.user
m = re.search(r";Propuesto por:([^\n]+)\n", self._contenido)
if m:
m = re.search(ur"\[\[(?:[Uu]suario(?:[_ ][Dd]iscusión)?|[Uu]ser(?:[_ ][Tt]alk)?):([^\]|]+)(?:\|[^\]]+)?\]\]", m.group(1))
if m:
proponente = m.group(1).strip()
#La fecha que debe constar es mes y año, la de la creación de la página es perfecta (¡y fuera regexp!)
fecha = timestamp(self._primera_fecha.isoformat())
fecha = datetime.strftime(fecha, "%B de %Y")
#Obtenemos los bytes del artículo mediante una consulta API.
params = {
"action": "query",
"titles": self._articulo,
"prop": "revisions",
"rvprop": "size",
"indexpageids": ""
}
q = api.Request(site, **params)
data = q.submit()
pageid = data["query"]["pageids"][0]
tamano = data['query']['pages'][pageid]['revisions'][0]['size']
#Recuento de votos.
#TODO: aquí faltan plantillas...
#(Nota: un page.templates() no descartaría las eliminadas con <s></s>.)
votos_pro = re.findall("(?<!<s>)(?:\{\{ *(?:\+|[Aa][_ ]?favor|(?:[Mm]uy|[Aa]lgo|[Vv]otos)[_ ]a[_ ]favor|[Ss]upport) *\}\})", self._contenido)
votos_contra = re.findall("(?<!<s>)(?:\{\{ *(?:-|[Ee]n[_ ]?contra|(?:[Mm]uy|[Aa]lgo|[Vv]otos)[_ ]en[_ ]contra|[Dd]enegado) *\}\})", self._contenido)
#TODO: fecha de cierre?
cierre = u"—"
plantillas = Templates(self._pagina)
c = plantillas.get_template_param("Cierre ACAD", 2)
cierre = ("desfavorable","favorable","desestimado")[int(c[0][1])] if c and c[0][1].isdigit() else u"—"
return proponente, fecha, "{:n} bytes".format(tamano), len(votos_pro), len(votos_contra), cierre
class Candidato_VAD(object):
u"""Este objeto obtiene los datos de cada artículo candidato."""
def __init__(self, articulo):
self._articulo = articulo
self._pagina = Page(site, u"Wikipedia:Candidatos a artículos destacados/%s" % articulo)
self._pagina_disc = Page(site, u"Wikipedia discusión:Candidatos a artículos destacados/%s" % articulo)
self._historial = self._pagina.getVersionHistory(step=500)
self._contenido = self._pagina.text
self._primera_edicion = self._historial[-1]
self._ultima_edicion = self._historial[0]
self._primera_fecha = self._primera_edicion[1]
self._ultima_fecha = self._ultima_edicion[1]
def participacion(self):
"""Determina el grado de participación."""
diferencia_fecha = self._ultima_fecha - self._primera_fecha
dias_sin_participar = datetime.today() - self._ultima_fecha
#si lleva al menos un día abierta pero sin editarse nada
if (self._primera_edicion == self._ultima_edicion) and (dias_sin_participar > timedelta(days=1)):
return 0
#si se ha llegado a publicar pero sin más ediciones, o ya pasan tres días desde la última edición
elif (self._primera_fecha != self._ultima_fecha) or (diferencia_fecha > timedelta(days=3)):
if dias_sin_participar > timedelta(days=3):
return 0
elif dias_sin_participar <= timedelta(days=2):
return 2
#obviously dias_sin_participar == 3
else:
return 1
elif self._primera_fecha == self._ultima_fecha == datetime.today():
return ""
return ""
def participantes(self):
"""Obtiene el número de participantes. (Equivalente a len(self._pagina.contributingUsers()).)"""
usuarios = set()
for edicion in self._historial:
usuarios.add(edicion[2])
return len(usuarios)
def observaciones(self):
"""Determina el valor de la columna 'observaciones'."""
if re.search("(?<!<s>)\{\{Cierre ACAD.*\}\}", self._contenido):
return "24h"
if (self._primera_fecha == self._ultima_fecha) or ((self._ultima_fecha - self._primera_fecha) <= timedelta(days=3)):
return "Nueva"
elif (datetime.today() - self._ultima_fecha) >= timedelta(days=3):
return "Emergencia"
return ""
def datos(self):
"""Obtenemos los siguentes datos: artículo, proponente, mes, tamaño, votos pro, votos contra y fecha cierre"""
locale.setlocale(locale.LC_ALL, sys.platform.startswith("win") and "Spanish_Spain" or "es_ES.UTF8")
#Por defecto (en caso de no poder extraer el proponente expuesto), el proponente
#será el creador de la candidatura.
proponente = self._primera_edicion[2]
m = re.search(r";Propuesto por:([^\n]+)\n", self._contenido)
if m:
m = re.search(ur"\[\[(?:[Uu]suario(?:[_ ][Dd]iscusión)?|[Uu]ser(?:[_ ][Tt]alk)?):([^\]|]+)(?:\|[^\]]+)?\]\]", m.group(1))
if m:
proponente = m.group(1).strip()
#La fecha que debe constar es mes y año, la de la creación de la página es perfecta (¡y fuera regexp!)
fecha = timestamp(self._primera_edicion[1].isoformat())
fecha = datetime.strftime(fecha, "%B de %Y")
#Obtenemos los bytes del artículo mediante una consulta API.
params = {
"action": "query",
"titles": self._articulo,
"prop": "revisions",
"rvprop": "size",
"indexpageids": ""
}
q = api.Request(site, **params)
data = q.submit()
pageid = data["query"]["pageids"][0]
tamano = data['query']['pages'][pageid]['revisions'][0]['size']
#Recuento de votos.
#TODO: aquí faltan plantillas...
#(Nota: un page.templates() no descartaría las eliminadas con <s></s>.)
votos_pro = re.findall("(?<!<s>)(?:\{\{ *(?:\+|[Aa][_ ]?favor|(?:[Mm]uy|[Aa]lgo|[Vv]otos)[_ ]a[_ ]favor|[Ss]upport) *\}\})", self._contenido)
votos_contra = re.findall("(?<!<s>)(?:\{\{ *(?:-|[Ee]n[_ ]?contra|(?:[Mm]uy|[Aa]lgo|[Vv]otos)[_ ]en[_ ]contra|[Dd]enegado) *\}\})", self._contenido)
#TODO: fecha de cierre?
cierre = u"—"
plantillas = Templates(self._pagina)
c = plantillas.get_template_param("Cierre ACAD", 2)
cierre = ("desfavorable","favorable","desestimado")[int(c[0][1])] if c and c[0][1].isdigit() else u"—"
return proponente, fecha, "{:n} bytes".format(tamano), len(votos_pro), len(votos_contra), cierre
class Candidatos(object):
"""Este objeto recopila todos los candidatos. Actualiza los datos de los artículos
de las tablas de [[Wikipedia:Candidatos a artículos destacados/Nominaciones]]
"""
def __init__(self):
self._pagina = Page(site, u"Wikipedia:Candidatos a artículos destacados/Nominaciones")
self._contenido = self._contenido_original = self._pagina.text
self._raiz = u"Wikipedia:Candidatos a artículos destacados"
self._re_raiz = ur"(?::?Wikipedia:Candidatos a artículos destacados)??"
patente = ur"\{\{%s/Temáticas\|(?P<art>[^|]+?)\|(?P<prop>[^|]+?)\|(?P<fecha>[^|]*?)\|(?P<tam>[^|]*?)\|(?P<fav>[^|]*?)\|(?P<cnt>[^|]*?)\|(?P<res>[^|]*?)\}\}" % self._re_raiz
patente = ur"\{\{%s/Temáticas(VAD)?\|([^|]+)\|[^}]+\}\}" % self._re_raiz
comentarios_fuera = re.sub("<!--.+?-->", "", self._contenido, flags=re.S | re.M)
self._elementos = re.findall(patente, comentarios_fuera, re.I)
verbose("t: %i | sct: %i | e:%r" % (len(self._contenido), len(comentarios_fuera), len(self._elementos)), 3)
def principal(self):
"""Actualiza [[Wikipedia:Candidatos a artículos destacados/Registro de errores]] y
prepara actualización de [[Wikipedia:Candidatos a artículos destacados]]"""
categoria = Category(site, u"Categoría:Wikipedia:Candidatos a artículos destacados")
paginas = categoria.articles()
#revisamos el contenido
candidatos = []
for pagina in paginas:
if pagina.namespace() == 1:
candidatos.append(pagina.title(withNamespace=False))
#TODO:
#los que faltan, son 'c. retirados' y debe retirarse la plantilla {{Candidato a destacado}} de la discusión?
#los que sobran, deben retirarse de [[Wikipedia:Candidatos a artículos destacados/Nominaciones]] al haber sido retirados?
elementos = [c if isinstance(c, basestring) else c[1] for c in self._elementos]
faltan = [u"{{A|%s}}" % candidato for candidato in candidatos if candidato not in elementos]
sobran = [u"{{A|%s}}" % candidato for candidato in elementos if candidato not in candidatos]
texto=""
if faltan:
texto += u"== faltan ==\nArtículos que '''no''' figuran en [[Wikiped"
texto += u"ia:Candidatos a artículos destacados/Nominaciones]], pero tienen {{tl|"
texto += u"Candidato a destacado}} en su página de discusión.\n\n"
texto += "*%s" % "\n*".join(faltan)
texto += "\n"
if sobran:
if texto: texto += "\n"
texto += u"== sobran ==\nArtículos que figuran en [[Wikipedia:Candid"
texto += u"atos a artículos destacados/Nominaciones]], pero no tienen {{tl|Candid"
texto += u"ato a destacado}} en su página de discusión.\n\n"
texto += "*%s" % "\n*".join(sobran)
texto += "\n"
if texto:
verbose(texto,2)
pagina_err = Page(site, u"Wikipedia:Candidatos a artículos destacados/Registro de errores")
if not args.test and texto != pagina_err.text:
pagina_err.text = texto
pagina_err.save(
"Bot: actualizando datos, %i no figuran en [[WP:CAD]] y %i "
"sin {{Candidato a destacado}} [total: %i]" % (
len(faltan),
len(sobran),
len(faltan)+len(sobran)
)
)
expreg_busqueda = re.compile(ur"\{\{%s/Temáticas\|(?P<art>[^|]+)\|(?P<prop>[^|]+)\|(?P<tam>[^|]+)\|(?P<fech>[^|]+)\|(?P<fav>[^|]+)\|(?P<con>[^|]+)\|(?P<cie>[^}]+)\}\}" % self._re_raiz)
expreg_busqueda_vad = re.compile(ur"\{\{%s/TemáticasVAD\|(?P<art>[^|]+)\|(?P<prop>[^|]+)\|(?P<fech>[^|]+)\|(?P<tam>[^|]+)\|(?P<rev>[^|]+)\|(?P<vot>[^|]+)\|(?P<cie>[^}]+)\}\}" % self._re_raiz)
patron_reemplazo = ur"{{{{%s/Temáticas|{art}|{prop}|{tam}|{fech}|{fav}|{con}|{cie}}}}}\n" % self._raiz
patron_reemplazo_vad = ur"{{{{%s/TemáticasVAD|{art}|{prop}|{fech}|{tam}|{rev}|{vot}|{cie}}}}}\n" % self._raiz
cand_dict = dict([(d[0],dict(zip(("prop",'tam',"fech",'fav',"con",'cie'),(d[1],d[2],d[3],d[4],d[5],d[6])))) for d in expreg_busqueda.findall(self._contenido)])
candvad_dict = dict([(d[0],dict(zip(("prop","fech",'tam','rev',"vot",'cie'),(d[1],d[2],d[3],d[4],d[5],d[6])))) for d in expreg_busqueda.findall(self._contenido)])
#nuevo_cand_dict=dict([(c,dict(zip(("prop","tam","fech","fav","con","cie"),Candidato(c).datos()))) for c in self._elementos])
nuevo_canddict={}; nuevo_candvad_dict={}; i=0
return
for vad, candidato in self._elementos:
#parche temporal bug candidato sin página cadidatura --coet 2014-11-21
if not vad:
try:
cand = Candidato_CAD(candidato)
except NoPage:
cand = lambda x: x
cand.datos = lambda: ("sin datos", "0", "sin datos", 0,0,"sin datos")
nuevo_canddict[candidato] = dict(zip(("prop","tam","fech","fav","con","cie"),cand.datos()))
if not cand_dict.has_key(candidato):
output(u"%s no està en candidatos" % candidato)
else:
i+=1
output(u"%i [[%s]]" % (i, candidato))
self._contenido = re.sub(
ur"\{\{%s/Temáticas *\| *%s *\|[^|]+\|[^|]+\|[^|]+\|[^|]+\|[^|]+\|[^}]+\}\}[\r\n\s]+" % (self._re_raiz, re.escape(candidato)),
patron_reemplazo.format(art=candidato, **nuevo_canddict[candidato]),
self._contenido
)
else:
try:
cand = Candidato_VAD(candidato)
except NoPage:
cand = lambda x: x
cand.datos = lambda: ("sin datos", "0", "sin datos", 0,0,"sin datos")
nuevo_candvad_dict[candidato] = dict(zip(("prop","fech","tam","rev","vot","cie"),cand.datos()))
if not candvad_dict.has_key(candidato):
output(u"%s no està en candidatos" % candidato)
else:
i+=1
output(u"%i [[%s]]" % (i, candidato))
self._contenido = re.sub(
ur"\{\{%s/TemáticasVAD *\| *%s *\|[^|]+\|[^|]+\|[^|]+\|[^|]+\|[^|]+\|[^}]+\}\}[\r\n\s]+" % (self._re_raiz, re.escape(candidato)),
patron_reemplazo.format(art=candidato, **nuevo_canddict[candidato]),
self._contenido
)
def recuento(self):
"""Prepara el recuento de las cabeceras."""
secciones_original = dict([(seccion[0], seccion[1].count(u"{{/Temáticas")) for seccion in re.findall(r"\{\{/Cabecera\|([^|]+)\|\d+ *\}\}(.*?\|\})", self._contenido_original, re.S)])
secciones = dict([(seccion[0], seccion[1].count(u"{{/Temáticas")) for seccion in re.findall(r"\{\{/Cabecera\|([^|]+)\|\d+ *\}\}(.*?\|\})", self._contenido, re.S)])
totales = dict([(seccion, (secciones_original[seccion], secciones[seccion])) for seccion in secciones_original.keys()])
total = 0
for seccion in totales:
total += totales[seccion][1]
if totales[seccion][0] != totales[seccion][1]:
self._contenido = re.sub(
ur"\{\{/Cabecera\|%s\|%i\}\}" % (seccion, totales[seccion][0]),
u"{{/Cabecera|%s|%i}}" % (seccion, totales[seccion][1]),
self._contenido
)
print "Total candidaturas: %i"%total
def editar(self):
"""Actualiza [[Wikipedia:Candidatos a artículos destacados]]."""
output("\n%s\n" % " cambios ".center(30, "="))
show_diff(self._contenido_original, self._contenido)
if not args.test and self._contenido_original != self._contenido:
self._pagina.text = self._contenido
self._pagina.save(u"Bot: actualizando tablas.")
def inicio(self):
self.principal()
self.recuento()
self.editar()
class Recordatorio(object):
"""Este objeto sirve para actualizar el contenido de la plantilla
{{Recordatorio CAD}} y el contador de [[Wikipedia:Candidatos a artículos destacados/Número]]
"""
def __init__(self):
self._pagina = Page(site, "Plantilla:Recordatorio CAD")
self._contenido = self._contenido_original = self._pagina.text
self._candidatos = candidatos._elementos
self.recuento = {}
def _plantillas_CAD(self):
"""Obtiene las plantilla {{RCAD}} de la plantilla {{Recordatorio CAD}} y las
almacena en dos variables para su posterior uso."""
patron_busqueda = r"\{\{RCAD\|(?P<art>[^|]+?)\|(?P<act>[^|]*?)\|(?P<usr>[^|]*?)\|(?P<obs>[^}]*?)\}\}"
self.plantillas = re.findall(r"\{\{RCAD\|([^|]+?)(?:\|[^|]+?){0,2}\|[^}]*?\}\}", self._contenido)
self._info_plantillas = dict(
[
(
pl.group("art"), {
"act": int(pl.group("act")) if pl.group("act").isdigit() else "",
"usr": int(pl.group("usr")) if pl.group("usr").isdigit() else 0,
"obs": pl.group("obs")
}
) for pl in re.finditer(patron_busqueda, self._contenido)
]
)
self.recuento["inicial"] = len(self.plantillas)
def _plantillas_VAD(self):
"""Obtiene las plantilla {{RVAD}} de la plantilla {{Recordatorio CAD}} y las
almacena en dos variables para su posterior uso."""
patron_busqueda = r"\{\{RVAD\|(?P<art>[^|]+?)\|(?P<act>[^|]*?)\|(?P<usr>[^|]*?)\|(?P<obs>[^}]*?)\}\}"
self.plantillasVAD = re.findall(r"\{\{RVAD\|([^|]+?)(?:\|[^|]+?){0,2}\|[^}]*?\}\}", self._contenido)
self._info_plantillas.update(
dict(
[
(
pl.group("art"), {
"act": int(pl.group("act")) if pl.group("act").isdigit() else "",
"usr": int(pl.group("usr")) if pl.group("usr").isdigit() else 0,
"obs": pl.group("obs")
}
) for pl in re.finditer(patron_busqueda, self._contenido)
]
)
)
self.recuento["inicialVAD"] = len(self.plantillasVAD)
def editar(self):
"""Actualiza [[Plantilla:Recordatorio CAD]]"""
output("\n%s\n" % " cambios ".center(30, "="))
show_diff(self._contenido_original, self._contenido)
if not args.test and self._contenido_original != self._contenido:
self._pagina.text = self._contenido
self._pagina.save(u"Bot: actualizando valores.")
def principal(self):
"""Prepara actualización de [[Plantilla:Recordatorio CAD]]"""
self._plantillas_CAD()
self._plantillas_VAD()
antiguos = []
nuevos = []
candidatos = [c if isinstance(c, basestring) else c[1] for c in self._candidatos]
#retira candidatos
for candidato in self._info_plantillas.keys():
if candidato not in self.plantillas: continue
if candidato not in candidatos:
self.plantillas.remove(candidato)
antiguos.append(candidato)
#inserta candidatos nuevos
for candidato in candidatos:
if candidato not in self.plantillas: continue
if not self._info_plantillas.has_key(candidato):
self.plantillas.append(candidato)
nuevos.append(candidato)
#retira votaciones
for candidato in self._info_plantillas.keys():
if candidato not in self.plantillasVAD: continue
if candidato not in candidatos:
self.plantillasVAD.remove(candidato)
antiguos.append(candidato)
#inserta votaciones nuevas
for candidato in candidatos:
if candidato not in self.plantillasVAD: continue
if not self._info_plantillas.has_key(candidato):
self.plantillasVAD.append(candidato)
nuevos.append(candidato)
verbose(
u">>>>>>>\ncandidatos:%r\nplantillas%r\ninfoplantillas%r\n<<<<<<<" % (
self._candidatos, self.plantillas, self._info_plantillas
), 2
)
#recorremos las candidaturas actualizando datos
#e informando de los cambios
patron_reemplazo = r"\{\{RCAD\|%s\|(?P<act>[^|]*?)\|(?P<usr>[^|]*?)\|(?P<obs>[^}]*?)\}\}"
patron_supresion = r"\{\{RCAD\|%s.*\}\}[\r\n\s]+"
cadena_reemplazo = ur"{{RCAD|%s|%s|%s|%s}}"
cadena_reemplazo_nueva = ur"\1{{RCAD|%s|%s|%s|%s}}\n|}"
patron_reemplazo_vad = r"\{\{RVAD\|%s\|(?P<act>[^|]*?)\|(?P<usr>[^|]*?)\|(?P<obs>[^}]*?)\}\}"
patron_supresion_vad = r"\{\{RVAD\|%s.*\}\}[\r\n\s]+"
cadena_reemplazo_vad = ur"{{RVAD|%s|%s|%s|%s}}"
cadena_reemplazo_nueva_vad = ur"\1{{RVAD|%s|%s|%s|%s}}\n|}"
for articulo in candidatos + antiguos:
verbose(u"examinando [[\3{lightblue}%s\3{default}]]" % articulo)
if articulo in antiguos:
verbose(u"\t\3{lightred}retirando la plantilla.\3{default}")
self._contenido = re.sub(patron_supresion % re.escape(articulo), "", self._contenido)
else:
if articulo in self.plantillas:
#parche temporal bug candidato sin página cadidatura --coet 2014-11-21
try:
candidato = Candidato_CAD(articulo)
participacion = candidato.participacion()
participantes = candidato.participantes()
observaciones = candidato.observaciones()
except NoPage:
participacion = participantes = observaciones = "sin datos"
verbose("%s: p1:%r | p2:%r | o:%r" % (candidato._articulo, participacion, participantes, observaciones), 2)
if articulo not in nuevos:
archivo = self._info_plantillas[articulo]
if participacion != archivo['act']:
notice("actividad", archivo['act'], participacion)
if participantes != archivo['usr']:
notice("usuarios", archivo['usr'], participantes)
if observaciones != archivo['obs']:
notice("otros", archivo['obs'], observaciones)
self._contenido = re.sub(
patron_reemplazo % re.escape(articulo),
cadena_reemplazo % (articulo, participacion, participantes, observaciones),
self._contenido
)
elif articulo in nuevos:
verbose(u"\t\3{lightgreen}añadiendo la plantilla.\3{default}")
self._contenido = re.sub(
r"(\|-\s+?|\{\{RCAD\|[^}]+?\}\}\s+?)\|}",
cadena_reemplazo_nueva % (articulo, participacion, participantes, observaciones),
self._contenido,
flags = re.S
)
elif articulo in self.plantillasVAD:
#parche temporal bug candidato sin página cadidatura --coet 2014-11-21
try:
candidato = Candidato_VAD(articulo)
participacion = candidato.participacion()
participantes = candidato.participantes()
observaciones = candidato.observaciones()
except NoPage:
participacion = participantes = observaciones = "sin datos"
verbose("%s: p1:%r | p2:%r | o:%r" % (candidato._articulo, participacion, participantes, observaciones), 2)
if articulo not in nuevos:
archivo = self._info_plantillas[articulo]
if participacion != archivo['act']:
notice("actividad", archivo['act'], participacion)
if participantes != archivo['usr']:
notice("usuarios", archivo['usr'], participantes)
if observaciones != archivo['obs']:
notice("otros", archivo['obs'], observaciones)
self._contenido = re.sub(
patron_reemplazo_vad % re.escape(articulo),
cadena_reemplazo_vad % (articulo, participacion, participantes, observaciones),
self._contenido
)
elif articulo in nuevos:
verbose(u"\t\3{lightgreen}añadiendo la plantilla.\3{default}")
self._contenido = re.sub(
r"(\|-\s+?|\{\{RVAD\|[^}]+?\}\}\s+?)\|}",
cadena_reemplazo_nueva_vad % (articulo, participacion, participantes, observaciones),
self._contenido,
flags = re.S
)
self._contenido = re.sub("Actualizado por .*\n", "Actualizado por ~~~~\n", self._contenido)
self.recuento.update({"nuevos": len(nuevos), "antiguos": len(antiguos), "final": len(self.plantillas), "finalVAD": len(self.plantillasVAD)})
def actualizar_contador_cad(self):
"""Actualiza [[Wikipedia:Candidatos a artículos destacados/Número]]"""
verbose(
u"plantillas añadidas: %i, plantillas retiradas: %i\nantes: %i | después: %i" % (
self.recuento["nuevos"],
self.recuento["antiguos"],
self.recuento["inicial"],
self.recuento['final']
)
)
texto = u"<noinclude>Pon aquí el número de "
texto += u"[[Wikipedia:Candidatos a artículos destacados|candidaturas para artículo destacado]] "
texto += u"que están actualmente en curso: </noinclude>%i" % self.recuento['final']
pagina = Page(site, u"Wikipedia:Candidatos a artículos destacados/Número")
if not args.test and texto != pagina.text:
pagina.text = texto
pagina.save(u"Bot: actualizando el contador: %i cand." % self.recuento['final'])
def actualizar_contador_vad(self):
"""Actualiza [[Wikipedia:Candidatos a artículos destacados/NúmeroVAD]]"""
verbose(
u"plantillas añadidas: %i, plantillas retiradas: %i\nantes: %i | después: %i" % (
self.recuento["nuevos"],
self.recuento["antiguos"],
self.recuento["inicial"],
self.recuento['finalVAD']
)
)
texto = u"<noinclude>Pon aquí el número de "
texto += u"[[Wikipedia:Candidatos a artículos destacados|candidaturas para artículo destacado]] "
texto += u"que están actualmente en curso: </noinclude>%i" % self.recuento['finalVAD']
pagina = Page(site, u"Wikipedia:Candidatos a artículos destacados/NúmeroVAD")
if not args.test and texto != pagina.text:
pagina.text = texto
pagina.save(u"Bot: actualizando el contador: %i cand." % self.recuento['finalVAD'])
def inicio(self):
self.principal()
self.editar()
self.actualizar_contador_cad()
self.actualizar_contador_vad()
def principal():
recordatorio.inicio()
candidatos.inicio()
def parametros():
#argumentos de entrada del usuario
args = lambda: x
args.recordatorio = args.candidatos = args.test = False
args.alert=1
for arg in handle_args():
if ":" in arg:
key, value = arg.split(":", 1)
if arg in ("-t", "--test"):
args.test = True
output("Modo \3{lightpurple}test\3{default} activado, no se editará.")
elif arg in ("-c", "--candidatos"):
args.candidatos = True
elif arg in ("-r", "--recordatorio"):
args.recordatorio = True
elif arg in ("-a", "--alert"):
args.alert = int(value)
return args
if __name__ == '__main__':
#Parámetros de funcionamiento.
"""
El parámetro -c o --candidatos actualizará los datos de las tablas de [[Wikipedia:Candidatos a artículos destacados]].
El parámetro -r o --recordatorio actualizará [[Plantilla:Recordatorio CAD]] y [[Wikipedia:Candidatos a artículos destacados/Número]].
La omisión de los dos hará la actualización de las tres tareas.
El parámetro -t o --test impide la edición.
"""
#argumentos de entrada del usuario
args = parametros()
#Funciones globales.
verbose = lambda msg, alert=args.alert: alert <= args.alert and output(msg)
notice = lambda x, y, z: verbose(
"\t%s de \3{lightpurple}%s\3{default} a \3{lightyellow}%s\3{default}." % (x, y, z)
)
timestamp = lambda x: datetime.strptime(x, "%Y-%m-%dT%H:%M:%SZ")
capitalize = lambda x: isinstance(x, basestring) and len(x)>0 and u"%s%s" % (x[0].upper(), x[1:]) or x
#Variables globales.
site = Site("es", user="TronaBot")
#¡Empezamos!
verbose(
"\n\n[{:%H:%M:%S}] ¡Comenzamos! rec:{a.recordatorio} cand:a.candidatos test:{a.test}" . format(
datetime.now(),
a=args
)
)
if args.candidatos:
candidatos = Candidatos()
candidatos.inicio()
elif args.recordatorio:
candidatos = Candidatos()
recordatorio = Recordatorio()
recordatorio.inicio()
else:
candidatos = Candidatos()
recordatorio = Recordatorio()
principal()