def __init__(self, main_page): self.les_mois = (u"janvier", u"février", u"mars", u"avril", u"mai", u"juin", u"juillet", u"août", u"septembre", u"octobre", u"novembre", u"décembre") self.site = pywikibot.Site() self.page_forum_nouveaux = main_page self.id_sql = self.page_forum_nouveaux.title().strip().encode('utf-8') self.match_title = re.compile(u"(\n|^)== *([^=].+[^=]) *==") self.match_date = re.compile( u"(?P<day>[0-9]+) *(?P<month>[^ ]+) *(?P<year>20[0-9]{2}) *à *(?P<hours>[0-9]{2}):(?P<minutes>[0-9]{2})" ) self.history = self.get_history(self.page_forum_nouveaux) if not self.history: pywikibot.output(u"Erreur : aucun historique existant !") return self.id = '' if main_page.title().split("/")[-1] != u"Wikipédia:Forum des nouveaux": self.id = main_page.title().split("/")[-1] # Les variables suivantes contiennent chacune différentes # informations, révision après révision de l'historique. # # self.history_text est uniquement une liste contenant le wikitexte # révision après révision. # self.history_titles est une liste de dict comme suit : # [{0:'== titre 1 ==', 1: '== titre 2==', 2: '== titre 3=='}}, # {0:'== titre 1 ==', 1: '== titre 2=='}] # self.history_sections est également une liste de dict comme suit : # [{'== titre 1 ==': 'contenu section 1', '== titre 2 ==': 'contenu section 2', # '== titre 3 ==': 'contenu section 3'}, {'== titre 1 ==': 'contenu section 1', # '== titre 2 ==': 'contenu section 2'}] self.history_text = [ history_entry[3] for history_entry in self.history ] self.history_titles = [ complements.extract_titles(text, beginning=None, match_title=self.match_title) for text in self.history_text ] self.history_sections = [ complements.extract_sections_with_titles( text, beginning=None, match_title=self.match_title) for text in self.history_text ] self.database = None self.reset_analyse_sections() # Listes des sections pour lesquelles le demandeur a déjà été averti. # Permet d'éviter d'avertir plusieurs fois d'affilée le demandeur # pendant le même lancement du script. self.sections_warned = list()
def __init__(self, main_page): self.les_mois = ( u"janvier", u"février", u"mars", u"avril", u"mai", u"juin", u"juillet", u"août", u"septembre", u"octobre", u"novembre", u"décembre" ) self.site = pywikibot.Site() self.page_forum_nouveaux = main_page self.id_sql = self.page_forum_nouveaux.title().strip().encode('utf-8') self.match_title = re.compile(u"(\n|^)== *([^=].+[^=]) *==") self.match_date = re.compile(u"(?P<day>[0-9]+) *(?P<month>[^ ]+) *(?P<year>20[0-9]{2}) *à *(?P<hours>[0-9]{2}):(?P<minutes>[0-9]{2})") self.history = self.get_history(self.page_forum_nouveaux) if not self.history: pywikibot.output(u"Erreur : aucun historique existant !") return self.id = '' if main_page.title().split("/")[-1] != u"Wikipédia:Forum des nouveaux": self.id = main_page.title().split("/")[-1] # Les variables suivantes contiennent chacune différentes # informations, révision après révision de l'historique. # # self.history_text est uniquement une liste contenant le wikitexte # révision après révision. # self.history_titles est une liste de dict comme suit : # [{0:'== titre 1 ==', 1: '== titre 2==', 2: '== titre 3=='}}, # {0:'== titre 1 ==', 1: '== titre 2=='}] # self.history_sections est également une liste de dict comme suit : # [{'== titre 1 ==': 'contenu section 1', '== titre 2 ==': 'contenu section 2', # '== titre 3 ==': 'contenu section 3'}, {'== titre 1 ==': 'contenu section 1', # '== titre 2 ==': 'contenu section 2'}] self.history_text = [history_entry[3] for history_entry in self.history] self.history_titles = [complements.extract_titles(text, beginning = None, match_title = self.match_title) for text in self.history_text] self.history_sections = [complements.extract_sections_with_titles(text, beginning = None, match_title = self.match_title) for text in self.history_text] self.database = None self.reset_analyse_sections() # Listes des sections pour lesquelles le demandeur a déjà été averti. # Permet d'éviter d'avertir plusieurs fois d'affilée le demandeur # pendant le même lancement du script. self.sections_warned = list()
def analyse_une_section(self, page, match_debut): # TODO : - gérer ou du moins éviter les problèmes en cas de doublons de titres. text = page.get() # Permet de ne garder que le texte contenant les requêtes à étudier, # car plusieurs sections se trouvent sur la même page. if match_debut == u'Requêtes en cours d\'examen': text = text[0:text.index(u"= Requêtes à traiter =")] elif match_debut == u'Requêtes à traiter': text = text[text.index(u"= Requêtes à traiter ="):] titres = complements.extract_titles( text, beginning=None, match_title=self.match_titre_requete) sections = complements.extract_sections(text, titres) return {'titres': titres, 'sections': sections}
def analyse_une_section(self, page, match_debut): # TODO : - gérer ou du moins éviter les problèmes en cas de doublons de titres. text = page.get() # Permet de ne garder que le texte contenant les requêtes à étudier, # car plusieurs sections se trouvent sur la même page. if match_debut == u'Requêtes en cours d\'examen': text = text[0:text.index(u"= Requêtes à traiter =")] elif match_debut == u'Requêtes à traiter': text = text[text.index(u"= Requêtes à traiter ="):] titres = complements.extract_titles(text, beginning = None, match_title = self.match_titre_requete) sections = complements.extract_sections(text, titres) return { 'titres': titres, 'sections': sections }
def archivage(self): """ Archivage ou suppression des requêtes classées (suivant le paramétrage du dictionnaire principal self.dict), dès lors qu'elles satisfont le délai configuré (self.dict['delai']['archivage'] et self.dict['delai']['suppression']). Les requêtes archivées sont transférées vers une sous-page de la page principale (self.main_page). Le chemin de cette sous-page est déterminée comme suit : self.main_page + '/' + self.archivePrefix + année en cours + Semaine XX (semaine en cours) ex : Wikipédia:Requête aux administrateurs/2012/Semaine 24 TODO (D): - mettre à jour la page principale d'archives lorsqu'une nouvelle page d'archives est créée. - vérifier l. 475 (new_text = archive_page.get() + '\\n' + text_to_archive) """ text = self.treated_page.get() titres = complements.extract_titles( text, beginning="", match_title=self.match_titre_requete) sections = complements.extract_sections(text, titres) now = datetime.datetime.now() #now = now + datetime.timedelta(days=11 - now.day) #debug : pour être le 11# currentWeekNumber = now.isocalendar()[1] previousWeekNumber = currentWeekNumber - 1 requests_to_archive = {} texts_requests_to_archive = {} requests_to_delete = [] # Début de la boucle d'analyse de chacune des sections, au cas par cas. for numero_section in sections: pywikibot.output('--------------------------------') pywikibot.output(sections[numero_section]) analyse = self.analyse_section(sections[numero_section]) if not analyse or not analyse['traitée']: # Une erreur a eu lieu ou le statut a été modifié continue date = analyse['date'] if not date: pywikibot.output(u'erreur : pas de date !') continue try: date = self.match_date.search(date) pywikibot.output(date.group('month')) # Il est préférable de reformater la date, toujours au format string # avant de la parser avec la commande datetime.datetime.strptime. # Ici, la date est normalisée suivant le format suivant : # jour mois année heures:minutes (tout en chiffres) # ex : 13 02 2012 23:34 # On préfèrera utiliser exclusivement des chiffres pour éviter # des problèmes liés aux accents sur le nom de certains mois, # tels février, décembre et août. text_date = u"%s %s %s %s:%s" % ( date.group('day'), self.les_mois[date.group('month')], date.group('year'), date.group('hours'), date.group('minutes')) date = datetime.datetime.strptime(text_date, u"%d %m %Y %H:%M") pywikibot.output(date) except: pywikibot.output(u'erreur: problème avec la date') continue pywikibot.output(now) pywikibot.output(self.dict['delai']['classement']) pywikibot.output((now - date)) pywikibot.output(((now - date).seconds / 3600) + (now - date).days * 24) if self.dict['archiver']: # Si l'archivage des requêtes est activé. if self.dict['delai']['archivage'] <= ( (now - date).seconds / 3600 + (now - date).days * 24): pywikibot.output(u'=> archivage') year = date.isocalendar()[0] weekNumber = date.isocalendar()[1] if not requests_to_archive.has_key(year): requests_to_archive[year] = {} if not requests_to_archive[year].has_key(weekNumber): requests_to_archive[year][weekNumber] = [] if not texts_requests_to_archive.has_key(year): texts_requests_to_archive[year] = {} if not texts_requests_to_archive[year].has_key(weekNumber): texts_requests_to_archive[year][weekNumber] = u"" requests_to_archive[year][weekNumber].append( sections[numero_section]) texts_requests_to_archive[year][weekNumber] += sections[ numero_section] else: pywikibot.output(u'=> pas d\'archivage') elif self.dict['supprimer']: # Sinon, si leur suppression est activée. if self.dict['delai']['suppression'] <= ( (now - date).seconds / 3600 + (now - date).days * 24): pywikibot.output(u'=> suppression') text = text.replace(sections[numero_section], '') requests_to_delete.append(sections[numero_section]) else: pywikibot.output(u'=> pas de suppression') # Fin de la boucle traitant les sections au cas par cas. # # Variables requests_to_archive et texts_requests_to_archive complètes, # si l'archivage est activé. if self.dict['archiver']: if not len(requests_to_archive): # Si rien n'est à archiver, on passe directement # au traitement suivant (de l'autre type de requêtes). return for year in requests_to_archive: pywikibot.output('_____________ year : %i _____________' % year) for week_number in requests_to_archive[year]: for section in requests_to_archive[year][week_number]: text = text.replace(section, '') pywikibot.output('_________ week_number : %i _________' % week_number) if week_number == 52: # Nouvelle année archive_page = pywikibot.Page( self.site, u"%s/%s%i/Semaine %i" % (self.main_page.title(asLink=False), self.archivePrefix, year, week_number)) else: archive_page = pywikibot.Page( self.site, u"%s/%s%i/Semaine %i" % (self.main_page.title(asLink=False), self.archivePrefix, year, week_number)) if archive_page.exists(): new_text = archive_page.get() while new_text[ -2:] != '\n\n': # Pour rajouter des sauts de lignes si nécessaire. new_text += '\n' new_text += texts_requests_to_archive[year][ week_number] else: new_text = texts_requests_to_archive[year][week_number] # Mise à jour de la page de classement en cours de traitement # ainsi que de la apge d'archive comment = (u"Archivage de %i requêtes" % len(requests_to_archive[year][week_number])) try: #pywikibot.showDiff(self.treated_page.get(), text) #pywikibot.output('******************************************************') #if archive_page.exists(): #pywikibot.showDiff(archive_page.get(), new_text) self.treated_page.put( text, comment=( comment + u" vers %s" % archive_page.title(asLink=True))) archive_page.put(new_text, comment=comment) except Exception, myexception: pywikibot.output("erreur type 2 : %s %s" % (type(myexception), myexception.args))
def classement(self): """ Classement des requêtes. Le bot prend en compte deux statuts, passés par le paramètre 'traitée' dans un modèle de début du type {{RA début}} : - 'oui' : la requête a été traitée - 'attente' : la requête est en attente Si le paramètre 'traitée' n'est pas renseigné, où s'il ne correspond à aucun des deux statuts connus par le bot, celui-ci ignore la requête, et la laisse où elle est. Les requêtes traitées sont classées dès leur que la date renseignée via le paramètre 'date' du modèle de début satisfait le délai suivant configuré dans le dictionnaire principal self.dict : self.dict['delai']['classement'] (en heures) Les requêtes possédant un statut correct et satisfaisant le délai configuré sont supprimées de la section "= Requêtes à traiter =" et sont envoyées - sur la page self.treated_page pour les requêtes traitées (page définie dans la fonction __init__) - dans la section "= Requêtes en attente =" pour les requêtes en attente Les requêtes précédemment en attente et n'ayant pas changé de statut depuis sont laissées telles quelles, dans l'ordre initial, dans la section "= Requêtes en attente =". Aucun paramètre n'est supporté pour cette fonction. """ self.text = self.main_page.get() self.text = self.text.replace(self.text_below_waiting_requests, u'') self.text = self.text.replace(self.text_below_untreated_requests, u'') #print self.text_below_waiting_requests #print self.text_below_untreated_requests #print self.text #print re.search(re.compile(u"= *Requêtes en cours d'examen *= *\n+(.*)\n*= *Requêtes à traiter *=", re.S), self.text) text_requetes_en_attente = re.search( re.compile( u"= *Requêtes en cours d'examen *= *\n+(.*)\n*= *Requêtes à traiter *=", re.S), self.text).group(1) pywikibot.output('text_requetes_en_attente') pywikibot.output(text_requetes_en_attente) pywikibot.output('--------------------------------') self.text = self.text.replace(text_requetes_en_attente, '') self.text = re.sub(u"(= Requêtes à traiter =\n*)\n", u"\\1\n%s" % text_requetes_en_attente, self.text) #self.text = re.sub(u"(= *Requêtes à traiter *=)", u"\\1%s" % text_requetes_en_attente, self.text) text_requetes_a_traiter = re.search(u"= *Requêtes à traiter *=", self.text).group(0) titres = complements.extract_titles( self.text, beginning=text_requetes_a_traiter, match_title=self.match_titre_requete) sections = complements.extract_sections(self.text, titres) self.text = re.sub(u"(= *Requêtes en cours d'examen *= *)", u"\\1%s" % self.text_below_waiting_requests, self.text) self.text = re.sub(u"(= *Requêtes à traiter *= *)", u"\\1%s" % self.text_below_untreated_requests, self.text) pywikibot.output(self.text) #for numero_section in sections: # print '--------------------------------' # print sections[numero_section] # Dictionnaire de classement des requêtes en fonction de # leur statut dict_requetes_par_statut = { 'traitée': list(), 'attente': list(), '': list( ) # requêtes sans statut ou ne répondant pas à la contrainte du délai } for numero_section in sections: pywikibot.output('--------------------------------') pywikibot.output(sections[numero_section]) analyse = self.analyse_section(sections[numero_section]) if analyse == None: # Une erreur a eu lieu print 'error: an unknown error occurred!' continue date = analyse['date'] traitee = analyse['traitée'] attente = analyse['attente'] if not traitee and not attente: # La requête n'a pas été traitée et pourtant elle n'est pas en attente. # La requête n'a donc soit pas de statut, soit celui-ci n'est pas # reconnu ou pas pris en charge. # ex : statuts 'autre' et 'autreavis' continue if not date and not attente: # Si la requête n'a pas de date et n'est pas en attente, # on la laisse l'endroit où elle est, pour éviter de # modifier l'ordre d'apparition des requêtes. pywikibot.output(u'aucune date renseignée') continue if attente: # Si la requête est en attente, on la classe dans le dictionnaire, # on la supprime du texte mais il est inutile d'aller plus loin # pour analyser la date, puisqu'elle sera automatiquement classée # dans la section "Requêtes en cours d'examen" self.text = self.text.replace(sections[numero_section], '') dict_requetes_par_statut['attente'].append( sections[numero_section]) continue try: date = self.match_date.search(date) pywikibot.output(date.group('month')) # Il est préférable de reformater la date, toujours au format string # avant de la parser avec la commande datetime.datetime.strptime. # Ici, la date est normalisée suivant le format suivant : # jour mois année heures:minutes (tout en chiffres) # ex : 13 02 2012 23:34 # On préfèrera utiliser exclusivement des chiffres pour éviter # des problèmes liés aux accents sur le nom de certains mois, # tels février, décembre et août. text_date = u"%s %s %s %s:%s" % ( date.group('day'), self.les_mois[date.group('month')], date.group('year'), date.group('hours'), date.group('minutes')) date = datetime.datetime.strptime(text_date, u"%d %m %Y %H:%M") pywikibot.output(date) except: pywikibot.output(u'erreur: problème avec la date') continue now = datetime.datetime.now() #now = now + datetime.timedelta(days=9 - now.day) #debug : pour être le 8# pywikibot.output(now) pywikibot.output(self.dict['delai']['classement']) pywikibot.output((now - date)) pywikibot.output(((now - date).seconds / 3600) + (now - date).days * 24) # Si la requête possède le délai requis pour être classée… if self.dict['delai']['classement'] <= ( (now - date).seconds / 3600 + (now - date).days * 24): pywikibot.output('=> classement') # …on place la requête dans la liste appropriée… dict_requetes_par_statut['traitée'].append( sections[numero_section]) # On supprime la requête de la section des requêtes à traiter. self.text = self.text.replace(sections[numero_section], '') else: # …sinon, on la met dans la liste dict_requetes_par_statut[''] pywikibot.output('=> pas de classement') dict_requetes_par_statut[''].append(sections[numero_section]) ## # Pour les tests ## for statut in dict_requetes_par_statut: pywikibot.output('=================================') pywikibot.output(statut) for requete in dict_requetes_par_statut[statut]: pywikibot.output('--------------------------------') pywikibot.output(requete) pywikibot.output('=================================') ## # Récupération des requêtes déjà acceptées/refusées # et création des textes adéquats pour chaque type de # requêtes. text_treated = self.treated_page.get() if text_treated: while text_treated[ -2:] != '\n\n': # Pour rajouter des sauts de lignes si nécessaire. text_treated += '\n' for requete in dict_requetes_par_statut['traitée']: text_treated += requete text_waiting = "" for requete in dict_requetes_par_statut['attente']: text_waiting += requete pywikibot.output('text_waiting') pywikibot.output(text_waiting) # text_untreated = "" # for requete in dict_requetes_par_statut['']: # text_untreated += requete # # if text_untreated: # while self.text[-2:] != '\n\n': # Pour rajouter des sauts de lignes si nécessaire. # self.text += '\n' # # self.text += text_untreated if text_waiting: # Permet d'avoir deux sauts de lignes après la dernière section, # en fin de page text_waiting = re.sub("(\n)*$", "\n\n", text_waiting) # Mise à jour #self.text = re.sub(u"(\n+= *[rR]equêtes *à *traiter *=)", u"%s\\1" % text_waiting, self.text) self.text = re.sub(u"\n+(= *[rR]equêtes *à *traiter *= *)", u"\n%s\\1" % text_waiting, self.text) #page = pywikibot.Page(self.site, u"User:ZéroBot/Wikipédia:Requête aux administrateurs") comment = u"Classement des requêtes (%i requête(s) traitée(s), %i requête(s) en attente)" % ( len(dict_requetes_par_statut['traitée']), len(dict_requetes_par_statut['attente'])) pywikibot.output(self.text) pywikibot.showDiff(self.main_page.get(), self.text) self.main_page.put(self.text, comment=comment) pywikibot.output(comment) #page = pywikibot.Page(self.site, u"User:ZéroBot/Wikipédia:Requête aux administrateurs/Requêtes traitées") comment = u"Classement des requêtes : %i requête(s) traitée(s)" % len( dict_requetes_par_statut['traitée']) self.treated_page.put(text_treated, comment=comment) pywikibot.output(comment)
def archivage(self): """ Archivage ou suppression des requêtes classées (suivant le paramétrage du dictionnaire principal self.dict), dès lors qu'elles satisfaisent le délai configuré (self.dict['delai']['archivage'] et self.dict['delai']['suppression']). Les requêtes archivées sont transférée vers une sous-page de la page principale (self.main_page), en rajoutant le suffixe '/Archives%i' avec %i un integer. Le bot détecte automatiquement la page d'archives en cours, et crée une nouvelle page dès que le nombre de 250 sections est atteint. TODO (D): - mettre à jour la page principale d'archives lorsqu'une nouvelle page d'archives est créée. - vérifier l.475 (new_text = archive_page.get() + '\\n' + text_to_archive) """ to_do = ['acceptees', 'refusees'] for type in to_do: if type == 'acceptees': page_en_cours = self.accepted_page #text = self.accepted_page.get() elif type == 'refusees': page_en_cours = self.refused_page #text = self.refused_page.get() pywikibot.output(page_en_cours) text = page_en_cours.get() if not text: pywikibot.output(u"Aucun texte dans la page !") continue titres = complements.extract_titles( text, beginning="", match_title=self.match_titre_requete) sections = complements.extract_sections(text, titres) text_to_archive = u"" requests_to_archive = [] requests_to_delete = [] # Début de la boucle d'analyse de chacune des sections, au cas par cas. for numero_section in sections: pywikibot.output('--------------------------------') pywikibot.output(titres[numero_section]) analyse = self.analyse_section(sections[numero_section]) if analyse == None: # Une erreur a eu lieu continue date = analyse['date'] statut = analyse['statut'] if not date: pywikibot.output(u'erreur : pas de date !') continue try: date = self.match_date.search(date) pywikibot.output(date.group('month')) # Il est préférable de reformater la date, toujours au format string # avant de la parser avec la commande datetime.strptime. # Ici, la date est normalisée suivant le format suivant : # jour mois année heures:minutes (tout en chiffres) # ex : 13 02 2012 23:34 # On préfèrera utiliser exclusivement des chiffres pour éviter # des problèmes liés aux accents sur le nom de certains mois, # tels février, décembre et août. text_date = u"%s %s %s %s:%s" % ( date.group('day'), self.les_mois[date.group('month')], date.group('year'), date.group('hours'), date.group('minutes')) date = datetime.strptime(text_date, u"%d %m %Y %H:%M") pywikibot.output("date is: %s" % date) except: pywikibot.output(u'erreur: problème avec la date') continue now = datetime.now() #pywikibot.output(now) pywikibot.output(u"délai classement : %i heures" % self.dict['delai']['classement']) #pywikibot.output((now-date)) pywikibot.output("from then to now: %s, that is %i hours" % ((now - date), ((now - date).seconds / 3600) + (now - date).days * 24)) if self.dict['archiver'][type]: # Si l'archivage des requêtes est activé. if self.dict['delai']['archivage'] <= ( (now - date).seconds / 3600 + (now - date).days * 24): pywikibot.output(u'=> archivage') text_to_archive += sections[numero_section] requests_to_archive.append(sections[numero_section]) text = text.replace(sections[numero_section], '') else: pywikibot.output(u'=> pas d\'archivage') elif self.dict['supprimer'][type]: # Sinon, si leur suppression est activée. if self.dict['delai']['suppression'] <= ( (now - date).seconds / 3600 + (now - date).days * 24): pywikibot.output(u'=> suppression') text = text.replace(sections[numero_section], '') requests_to_delete.append(sections[numero_section]) else: pywikibot.output(u'=> pas de suppression') # Fin de la boucle traitant les sections au cas par cas. # # La variable text_to_archive contient désormais la totalité des requêtes # à archiver (texte), si l'archivage est activé pour le type de requêtes en # cours de traitement. # # La variable requests_to_archive contient désormais la liste des requêtes # à archiver, si l'archivage est activé pour le type de requêtes en # cours de traitement. if self.dict['archiver'][type]: if not text_to_archive: # Si rien n'est à archiver, on passe directement # au traitement suivant (de l'autre type de requêtes). continue # Trouver le numéro de la page d'archive en cours archiveNumber = 1 archive_page = None while True: previous_archive_page = archive_page archive_page = pywikibot.Page( self.site, self.main_page.title(asLink=False) + "/%s%i" % (self.archivePrefix, archiveNumber)) if not archive_page.exists(): break archiveNumber += 1 if previous_archive_page != None: archiveNumber -= 1 archive_page = previous_archive_page pywikibot.output(archive_page) #pywikibot.output(text_to_archive) # La variable archiveNumber contient à présent le numéro # de la page d'archive en cours. # Si la page d'archive existe (si elle n'existe pas, c'est qu'aucune page # d'archive n'a été trouvée par le bot. if archive_page.exists(): # On compte le nombre de requêtes déjà présentes dans # la page d'archive en cours. # Pour cela, on remplace chaque titre de section par '{[$REQUETE$]}' # et on compte le nombre de '{[$REQUETE$]}'. nombre_de_sections = re.sub( self.match_titre_requete, '{[$REQUETE$]}', archive_page.get()).count('{[$REQUETE$]}') #print re.sub(self.match_titre_requete, '{[$REQUETE$]}', text) pywikibot.output('nombre_de_sections = %i' % nombre_de_sections) if nombre_de_sections > 250: old_archiveNumber = archiveNumber old_archive_page = archive_page # On récupère la dernière requête pour donner la dernière date # de la page d'archive. text_temp = old_archive_page.get() old_archives = complements.extract_sections( text_temp, complements.extract_titles( text_temp, "", self.match_titre_requete)) last_archive = old_archives[len(old_archives) - 1] templates = textlib.extract_templates_and_params( last_archive) for template in templates: pywikibot.output(template) if template[ 0] == self.template_title: #u'RA début': #modifié (todo A-1) statut = template[1]['statut'] date = template[1]['date'] pywikibot.output(date) # On arrête d'analyser les modèles, étant donné qu'on a trouvé # celui qui nous intéresse. break if date: try: pywikibot.output(date) last_date = self.match_date.search(date) pywikibot.output(last_date) last_date = u"%s %s %s" % ( last_date.group('day'), last_date.group('month'), last_date.group('year')) pywikibot.output(last_date) except Exception, myexception: pywikibot.output( u'%s %s' % (type(myexception), myexception.args)) pywikibot.output( u'erreur: problème avec la date') else: pywikibot.output(u'erreur : pas de date !') # La variable last_date contient désormais la date de la dernière # requête de la page d'archives. archiveNumber += 1 archive_page = pywikibot.Page( self.site, self.main_page.title(asLink=False) + "/%s%i" % (self.archivePrefix, archiveNumber)) new_text = text_to_archive pywikibot.output( u"Plus de 250 requêtes archivées -> création d'une nouvelle page d'archive (n°%i)" % archiveNumber) # Mise à jour de la page d'archives principale main_archive_page = pywikibot.Page( self.site, self.main_page.title() + u"/Archives") text_temp = main_archive_page.get() text_temp = re.sub( u"(\# *\[\[%s\]\]) *" % old_archive_page.title(asLink=False), u"\\1 (jusqu'au %s)\n# %s" % (last_date, archive_page.title(asLink=True)), text_temp) main_archive_page.put( text_temp, comment=u"Création d'une nouvelle page d'archives") else: pywikibot.output( u"Moins de 250 requêtes archivées -> page d'archive actuelle (n°%i)" % archiveNumber) new_text = archive_page.get() while new_text[ -2:] != '\n\n': # Pour rajouter des sauts de lignes si nécessaire. new_text += '\n' new_text += text_to_archive else: # Aucune page d'archive n'a été trouvée par le bot. pywikibot.output( u"1ère page d'archive ! Aucune ne semble exister actuellement…" ) new_text = text_to_archive # Mise à jour de la page de classement en cours de traitement # ainsi que de la apge d'archive comment = (u"Archivage de %i requêtes" % len(requests_to_archive)) try: # pwb_error pywikibot.showDiff(page_en_cours.get(), text) pywikibot.output( '******************************************************' ) # pwb_error if archive_page.exists(): # pwb_error pywikibot.showDiff(archive_page.get(), new_text) page_en_cours.put( text, comment=( comment + u" vers %s" % archive_page.title(asLink=True))) archive_page.put(new_text, comment=comment) except Exception, myexception: pywikibot.output("erreur type 2")
def archivage(self): """ Archivage ou suppression des requêtes classées (suivant le paramétrage du dictionnaire principal self.dict), dès lors qu'elles satisfont le délai configuré (self.dict['delai']['archivage'] et self.dict['delai']['suppression']). Les requêtes archivées sont transférées vers une sous-page de la page principale (self.main_page). Le chemin de cette sous-page est déterminée comme suit : self.main_page + '/' + self.archivePrefix + année en cours + Semaine XX (semaine en cours) ex : Wikipédia:Requête aux administrateurs/2012/Semaine 24 TODO (D): - mettre à jour la page principale d'archives lorsqu'une nouvelle page d'archives est créée. - vérifier l. 475 (new_text = archive_page.get() + '\\n' + text_to_archive) """ text = self.treated_page.get() titres = complements.extract_titles(text, beginning = "", match_title = self.match_titre_requete) sections = complements.extract_sections(text, titres) now = datetime.datetime.now() #now = now + datetime.timedelta(days=11 - now.day) #debug : pour être le 11# currentWeekNumber = now.isocalendar()[1] previousWeekNumber = currentWeekNumber - 1 requests_to_archive = {} texts_requests_to_archive = {} requests_to_delete = [] # Début de la boucle d'analyse de chacune des sections, au cas par cas. for numero_section in sections: pywikibot.output('--------------------------------') pywikibot.output(sections[numero_section]) analyse = self.analyse_section(sections[numero_section]) if not analyse or not analyse['traitée']: # Une erreur a eu lieu ou le statut a été modifié continue date = analyse['date'] if not date: pywikibot.output(u'erreur : pas de date !') continue try: date = self.match_date.search(date) pywikibot.output(date.group('month')) # Il est préférable de reformater la date, toujours au format string # avant de la parser avec la commande datetime.datetime.strptime. # Ici, la date est normalisée suivant le format suivant : # jour mois année heures:minutes (tout en chiffres) # ex : 13 02 2012 23:34 # On préfèrera utiliser exclusivement des chiffres pour éviter # des problèmes liés aux accents sur le nom de certains mois, # tels février, décembre et août. text_date = u"%s %s %s %s:%s" % (date.group('day'), self.les_mois[date.group('month')], date.group('year'), date.group('hours'), date.group('minutes')) date = datetime.datetime.strptime(text_date, u"%d %m %Y %H:%M") pywikibot.output(date) except: pywikibot.output(u'erreur: problème avec la date') continue pywikibot.output(now) pywikibot.output(self.dict['delai']['classement']) pywikibot.output((now-date)) pywikibot.output(((now-date).seconds/3600) + (now-date).days*24) if self.dict['archiver']: # Si l'archivage des requêtes est activé. if self.dict['delai']['archivage'] <= ((now-date).seconds/3600 + (now-date).days*24): pywikibot.output(u'=> archivage') weekNumber = date.isocalendar()[1] if not requests_to_archive.has_key(weekNumber): requests_to_archive[weekNumber] = [] if not texts_requests_to_archive.has_key(weekNumber): texts_requests_to_archive[weekNumber] = u"" requests_to_archive[weekNumber].append(sections[numero_section]) texts_requests_to_archive[weekNumber] += sections[numero_section] else: pywikibot.output(u'=> pas d\'archivage') elif self.dict['supprimer']: # Sinon, si leur suppression est activée. if self.dict['delai']['suppression'] <= ((now-date).seconds/3600 + (now-date).days*24): pywikibot.output(u'=> suppression') text = text.replace(sections[numero_section], '') requests_to_delete.append(sections[numero_section]) else: pywikibot.output(u'=> pas de suppression') # Fin de la boucle traitant les sections au cas par cas. # # Variables requests_to_archive et texts_requests_to_archive complètes, # si l'archivage est activé. if self.dict['archiver']: if not len(requests_to_archive): # Si rien n'est à archiver, on passe directement # au traitement suivant (de l'autre type de requêtes). return for week_number in requests_to_archive: for section in requests_to_archive[week_number]: text = text.replace(section, '') pywikibot.output('_________ week_number : %i _________' % week_number) archive_page = pywikibot.Page(self.site, u"%s/%s%i/Semaine %i" % (self.main_page.title(asLink = False), self.archivePrefix, now.isocalendar()[0], week_number)) if archive_page.exists(): new_text = archive_page.get() while new_text[-2:] != '\n\n': # Pour rajouter des sauts de lignes si nécessaire. new_text += '\n' new_text += texts_requests_to_archive[week_number] else: new_text = texts_requests_to_archive[week_number] # Mise à jour de la page de classement en cours de traitement # ainsi que de la apge d'archive comment = (u"Archivage de %i requêtes" % len(requests_to_archive[week_number])) try: pywikibot.showDiff(self.treated_page.get(), text) pywikibot.output('******************************************************') if archive_page.exists(): pywikibot.showDiff(archive_page.get(), new_text) self.treated_page.put(text, comment = (comment + u" vers %s" % archive_page.title(asLink = True))) archive_page.put(new_text, comment = comment) except Exception, myexception: pywikibot.output("erreur type 2 : %s %s" % (type(myexception), myexception.args))
def classement(self): """ Classement des requêtes. Le bot prend en compte deux statuts, passés par le paramètre 'traitée' dans un modèle de début du type {{RA début}} : - 'oui' : la requête a été traitée - 'attente' : la requête est en attente Si le paramètre 'traitée' n'est pas renseigné, où s'il ne correspond à aucun des deux statuts connus par le bot, celui-ci ignore la requête, et la laisse où elle est. Les requêtes traitées sont classées dès leur que la date renseignée via le paramètre 'date' du modèle de début satisfait le délai suivant configuré dans le dictionnaire principal self.dict : self.dict['delai']['classement'] (en heures) Les requêtes possédant un statut correct et satisfaisant le délai configuré sont supprimées de la section "= Requêtes à traiter =" et sont envoyées - sur la page self.treated_page pour les requêtes traitées (page définie dans la fonction __init__) - dans la section "= Requêtes en attente =" pour les requêtes en attente Les requêtes précédemment en attente et n'ayant pas changé de statut depuis sont laissées telles quelles, dans l'ordre initial, dans la section "= Requêtes en attente =". Aucun paramètre n'est supporté pour cette fonction. """ self.text = self.main_page.get() self.text = self.text.replace(self.text_below_waiting_requests, u'') self.text = self.text.replace(self.text_below_untreated_requests, u'') #print self.text_below_waiting_requests #print self.text_below_untreated_requests #print self.text #print re.search(re.compile(u"= *Requêtes en cours d'examen *= *\n+(.*)\n*= *Requêtes à traiter *=", re.S), self.text) text_requetes_en_attente = re.search(re.compile(u"= *Requêtes en cours d'examen *= *\n+(.*)\n*= *Requêtes à traiter *=", re.S), self.text).group(1) pywikibot.output('text_requetes_en_attente') pywikibot.output(text_requetes_en_attente) pywikibot.output('--------------------------------') self.text = self.text.replace(text_requetes_en_attente, '') self.text = re.sub(u"(= Requêtes à traiter =\n*)\n", u"\\1\n%s" % text_requetes_en_attente, self.text) #self.text = re.sub(u"(= *Requêtes à traiter *=)", u"\\1%s" % text_requetes_en_attente, self.text) text_requetes_a_traiter = re.search(u"= *Requêtes à traiter *=", self.text).group(0) titres = complements.extract_titles(self.text, beginning = text_requetes_a_traiter, match_title = self.match_titre_requete) sections = complements.extract_sections(self.text, titres) self.text = re.sub(u"(= *Requêtes en cours d'examen *= *)", u"\\1%s" % self.text_below_waiting_requests, self.text) self.text = re.sub(u"(= *Requêtes à traiter *= *)", u"\\1%s" % self.text_below_untreated_requests, self.text) pywikibot.output(self.text) #for numero_section in sections: # print '--------------------------------' # print sections[numero_section] # Dictionnaire de classement des requêtes en fonction de # leur statut dict_requetes_par_statut = { 'traitée': list(), 'attente': list(), '': list() # requêtes sans statut ou ne répondant pas à la contrainte du délai } for numero_section in sections: pywikibot.output('--------------------------------') pywikibot.output(sections[numero_section]) analyse = self.analyse_section(sections[numero_section]) if analyse == None: # Une erreur a eu lieu continue date = analyse['date'] traitee = analyse['traitée'] attente = analyse['attente'] if not traitee and not attente: # La requête n'a pas été traitée et pourtant elle n'est pas en attente. # La requête n'a donc soit pas de statut, soit celui-ci n'est pas # reconnu ou pas pris en charge. # ex : statuts 'autre' et 'autreavis' continue if not date and not attente: # Si la requête n'a pas de date et n'est pas en attente, # on la laisse l'endroit où elle est, pour éviter de # modifier l'ordre d'apparition des requêtes. pywikibot.output(u'aucune date renseignée') continue if attente: # Si la requête est en attente, on la classe dans le dictionnaire, # on la supprime du texte mais il est inutile d'aller plus loin # pour analyser la date, puisqu'elle sera automatiquement classée # dans la section "Requêtes en cours d'examen" self.text = self.text.replace(sections[numero_section], '') dict_requetes_par_statut['attente'].append(sections[numero_section]) continue try: date = self.match_date.search(date) pywikibot.output(date.group('month')) # Il est préférable de reformater la date, toujours au format string # avant de la parser avec la commande datetime.datetime.strptime. # Ici, la date est normalisée suivant le format suivant : # jour mois année heures:minutes (tout en chiffres) # ex : 13 02 2012 23:34 # On préfèrera utiliser exclusivement des chiffres pour éviter # des problèmes liés aux accents sur le nom de certains mois, # tels février, décembre et août. text_date = u"%s %s %s %s:%s" % (date.group('day'), self.les_mois[date.group('month')], date.group('year'), date.group('hours'), date.group('minutes')) date = datetime.datetime.strptime(text_date, u"%d %m %Y %H:%M") pywikibot.output(date) except: pywikibot.output(u'erreur: problème avec la date') continue now = datetime.datetime.now() #now = now + datetime.timedelta(days=9 - now.day) #debug : pour être le 8# pywikibot.output(now) pywikibot.output(self.dict['delai']['classement']) pywikibot.output((now-date)) pywikibot.output(((now-date).seconds/3600) + (now-date).days*24) # Si la requête possède le délai requis pour être classée… if self.dict['delai']['classement'] <= ((now-date).seconds/3600 + (now-date).days*24): pywikibot.output('=> classement') # …on place la requête dans la liste appropriée… dict_requetes_par_statut['traitée'].append(sections[numero_section]) # On supprime la requête de la section des requêtes à traiter. self.text = self.text.replace(sections[numero_section], '') else: # …sinon, on la met dans la liste dict_requetes_par_statut[''] pywikibot.output('=> pas de classement') dict_requetes_par_statut[''].append(sections[numero_section]) ## # Pour les tests ## for statut in dict_requetes_par_statut: pywikibot.output('=================================') pywikibot.output(statut) for requete in dict_requetes_par_statut[statut]: pywikibot.output('--------------------------------') pywikibot.output(requete) pywikibot.output('=================================') ## # Récupération des requêtes déjà acceptées/refusées # et création des textes adéquats pour chaque type de # requêtes. text_treated = self.treated_page.get() if text_treated: while text_treated[-2:] != '\n\n': # Pour rajouter des sauts de lignes si nécessaire. text_treated += '\n' for requete in dict_requetes_par_statut['traitée']: text_treated += requete text_waiting = "" for requete in dict_requetes_par_statut['attente']: text_waiting += requete pywikibot.output('text_waiting') pywikibot.output(text_waiting) # text_untreated = "" # for requete in dict_requetes_par_statut['']: # text_untreated += requete # # if text_untreated: # while self.text[-2:] != '\n\n': # Pour rajouter des sauts de lignes si nécessaire. # self.text += '\n' # # self.text += text_untreated if text_waiting: # Permet d'avoir deux sauts de lignes après la dernière section, # en fin de page text_waiting = re.sub("(\n)*$", "\n\n", text_waiting) # Mise à jour #self.text = re.sub(u"(\n+= *[rR]equêtes *à *traiter *=)", u"%s\\1" % text_waiting, self.text) self.text = re.sub(u"\n+(= *[rR]equêtes *à *traiter *= *)", u"\n%s\\1" % text_waiting, self.text) #page = pywikibot.Page(self.site, u"User:ZéroBot/Wikipédia:Requête aux administrateurs") comment = u"Classement des requêtes (%i requête(s) traitée(s), %i requête(s) en attente)" % (len(dict_requetes_par_statut['traitée']), len(dict_requetes_par_statut['attente'])) pywikibot.output(self.text) pywikibot.showDiff(self.main_page.get(), self.text) self.main_page.put(self.text, comment = comment) pywikibot.output(comment) #page = pywikibot.Page(self.site, u"User:ZéroBot/Wikipédia:Requête aux administrateurs/Requêtes traitées") comment = u"Classement des requêtes : %i requête(s) traitée(s)" % len(dict_requetes_par_statut['traitée']) self.treated_page.put(text_treated, comment = comment) pywikibot.output(comment)
def archivage(self): """ Archivage ou suppression des requêtes classées (suivant le paramétrage du dictionnaire principal self.dict), dès lors qu'elles satisfaisent le délai configuré (self.dict['delai']['archivage'] et self.dict['delai']['suppression']). Les requêtes archivées sont transférée vers une sous-page de la page principale (self.main_page), en rajoutant le suffixe '/Archives%i' avec %i un integer. Le bot détecte automatiquement la page d'archives en cours, et crée une nouvelle page dès que le nombre de 250 sections est atteint. TODO (D): - mettre à jour la page principale d'archives lorsqu'une nouvelle page d'archives est créée. - vérifier l.475 (new_text = archive_page.get() + '\\n' + text_to_archive) """ to_do = ['acceptees', 'refusees'] for type in to_do: if type == 'acceptees': page_en_cours = self.accepted_page #text = self.accepted_page.get() elif type == 'refusees': page_en_cours = self.refused_page #text = self.refused_page.get() pywikibot.output(page_en_cours) text = page_en_cours.get() if not text: pywikibot.output(u"Aucun texte dans la page !") continue titres = complements.extract_titles(text, beginning = "", match_title = self.match_titre_requete) sections = complements.extract_sections(text, titres) text_to_archive = u"" requests_to_archive = [] requests_to_delete = [] # Début de la boucle d'analyse de chacune des sections, au cas par cas. for numero_section in sections: pywikibot.output('--------------------------------') pywikibot.output(titres[numero_section]) analyse = self.analyse_section(sections[numero_section]) if analyse == None: # Une erreur a eu lieu continue date = analyse['date'] statut = analyse['statut'] if not date: pywikibot.output(u'erreur : pas de date !') continue try: date = self.match_date.search(date) pywikibot.output(date.group('month')) # Il est préférable de reformater la date, toujours au format string # avant de la parser avec la commande datetime.strptime. # Ici, la date est normalisée suivant le format suivant : # jour mois année heures:minutes (tout en chiffres) # ex : 13 02 2012 23:34 # On préfèrera utiliser exclusivement des chiffres pour éviter # des problèmes liés aux accents sur le nom de certains mois, # tels février, décembre et août. text_date = u"%s %s %s %s:%s" % (date.group('day'), self.les_mois[date.group('month')], date.group('year'), date.group('hours'), date.group('minutes')) date = datetime.strptime(text_date, u"%d %m %Y %H:%M") pywikibot.output("date is: %s" % date) except: pywikibot.output(u'erreur: problème avec la date') continue now = datetime.now() #pywikibot.output(now) pywikibot.output(u"délai classement : %i heures" % self.dict['delai']['classement']) #pywikibot.output((now-date)) pywikibot.output("from then to now: %s, that is %i hours" % ((now-date), ((now-date).seconds/3600) + (now-date).days*24)) if self.dict['archiver'][type]: # Si l'archivage des requêtes est activé. if self.dict['delai']['archivage'] <= ((now-date).seconds/3600 + (now-date).days*24): pywikibot.output(u'=> archivage') text_to_archive += sections[numero_section] requests_to_archive.append(sections[numero_section]) text = text.replace(sections[numero_section], '') else: pywikibot.output(u'=> pas d\'archivage') elif self.dict['supprimer'][type]: # Sinon, si leur suppression est activée. if self.dict['delai']['suppression'] <= ((now-date).seconds/3600 + (now-date).days*24): pywikibot.output(u'=> suppression') text = text.replace(sections[numero_section], '') requests_to_delete.append(sections[numero_section]) else: pywikibot.output(u'=> pas de suppression') # Fin de la boucle traitant les sections au cas par cas. # # La variable text_to_archive contient désormais la totalité des requêtes # à archiver (texte), si l'archivage est activé pour le type de requêtes en # cours de traitement. # # La variable requests_to_archive contient désormais la liste des requêtes # à archiver, si l'archivage est activé pour le type de requêtes en # cours de traitement. if self.dict['archiver'][type]: if not text_to_archive: # Si rien n'est à archiver, on passe directement # au traitement suivant (de l'autre type de requêtes). continue # Trouver le numéro de la page d'archive en cours archiveNumber=1 archive_page = None while True: previous_archive_page = archive_page archive_page = pywikibot.Page(self.site, self.main_page.title(asLink = False) + "/%s%i" % (self.archivePrefix, archiveNumber)) if not archive_page.exists(): break archiveNumber += 1 if previous_archive_page != None: archiveNumber -= 1 archive_page = previous_archive_page pywikibot.output(archive_page) #pywikibot.output(text_to_archive) # La variable archiveNumber contient à présent le numéro # de la page d'archive en cours. # Si la page d'archive existe (si elle n'existe pas, c'est qu'aucune page # d'archive n'a été trouvée par le bot. if archive_page.exists(): # On compte le nombre de requêtes déjà présentes dans # la page d'archive en cours. # Pour cela, on remplace chaque titre de section par '{[$REQUETE$]}' # et on compte le nombre de '{[$REQUETE$]}'. nombre_de_sections = re.sub(self.match_titre_requete, '{[$REQUETE$]}', archive_page.get()).count('{[$REQUETE$]}') #print re.sub(self.match_titre_requete, '{[$REQUETE$]}', text) pywikibot.output('nombre_de_sections = %i' % nombre_de_sections) if nombre_de_sections > 250: old_archiveNumber = archiveNumber old_archive_page = archive_page # On récupère la dernière requête pour donner la dernière date # de la page d'archive. text_temp = old_archive_page.get() old_archives = complements.extract_sections(text_temp, complements.extract_titles(text_temp, "", self.match_titre_requete)) last_archive = old_archives[len(old_archives) - 1] templates = textlib.extract_templates_and_params(last_archive) for template in templates: pywikibot.output(template) if template[0] == self.template_title:#u'RA début': #modifié (todo A-1) statut = template[1]['statut'] date = template[1]['date'] pywikibot.output(date) # On arrête d'analyser les modèles, étant donné qu'on a trouvé # celui qui nous intéresse. break if date: try: pywikibot.output(date) last_date = self.match_date.search(date) pywikibot.output(last_date) last_date = u"%s %s %s" % (last_date.group('day'), last_date.group('month'), last_date.group('year')) pywikibot.output(last_date) except Exception, myexception: pywikibot.output(u'%s %s' % (type(myexception), myexception.args)) pywikibot.output(u'erreur: problème avec la date') else: pywikibot.output(u'erreur : pas de date !') # La variable last_date contient désormais la date de la dernière # requête de la page d'archives. archiveNumber += 1 archive_page = pywikibot.Page(self.site, self.main_page.title(asLink = False) + "/%s%i" % (self.archivePrefix, archiveNumber)) new_text = text_to_archive pywikibot.output(u"Plus de 250 requêtes archivées -> création d'une nouvelle page d'archive (n°%i)" % archiveNumber) # Mise à jour de la page d'archives principale main_archive_page = pywikibot.Page(self.site, self.main_page.title() + u"/Archives") text_temp = main_archive_page.get() text_temp = re.sub(u"(\# *\[\[%s\]\]) *" % old_archive_page.title(asLink = False), u"\\1 (jusqu'au %s)\n# %s" % (last_date, archive_page.title(asLink = True)), text_temp) main_archive_page.put(text_temp, comment = u"Création d'une nouvelle page d'archives") else: pywikibot.output(u"Moins de 250 requêtes archivées -> page d'archive actuelle (n°%i)" % archiveNumber) new_text = archive_page.get() while new_text[-2:] != '\n\n': # Pour rajouter des sauts de lignes si nécessaire. new_text += '\n' new_text += text_to_archive else: # Aucune page d'archive n'a été trouvée par le bot. pywikibot.output(u"1ère page d'archive ! Aucune ne semble exister actuellement…") new_text = text_to_archive # Mise à jour de la page de classement en cours de traitement # ainsi que de la apge d'archive comment = (u"Archivage de %i requêtes" % len(requests_to_archive)) try: # pwb_error pywikibot.showDiff(page_en_cours.get(), text) pywikibot.output('******************************************************') # pwb_error if archive_page.exists(): # pwb_error pywikibot.showDiff(archive_page.get(), new_text) page_en_cours.put(text, comment = (comment + u" vers %s" % archive_page.title(asLink = True))) archive_page.put(new_text, comment = comment) except Exception, myexception: pywikibot.output("erreur type 2")