Utilisateur:Cuagga/Conciliabule Cuaggbot
Évaluation
[modifier | modifier le code]- Pour les évaluations, tu peux regarder Utilisateur:LD/Contenu/Outils et modèles/Maintenance/Évaluation (doc très incomplet mais a le mérite d'exister disons) pour la récupération ; LD • m'écrire • 30 juin 2021 à 18:21 (CEST)
- Il vaut mieux que j'utilise le modèle Wikiprojet ou le modèle Evaluation ?
- Je dirais le Wikiprojet car sa maintenance est interne à Wikipédia et parce que les modèles de statistiques (Projet:Évaluation/Statistiques) sont liés à OrlodrimBot, si son intervention venait à s'interrompre... LD • m'écrire • 30 juin 2021 à 18:35 (CEST)
Github pour le projet
- Quelques remarques sur les évaluations récentes :
- Il faudrait vérifier que le projet existe (ex) parce que dans le cas contraire, l'évaluation est sans intérêt, il faut un minimum de suivi et de fédération ; Catégorie:Article du projet Armes d'avancement inconnu ~200 pdd dans le vide
- Privilégier la forme étendue du Wikicode (comme ceci)
- Apposer les projets en une fois si possible
- Traiter en premier les ébauches, plutôt que de laisser un avancement inconnu ; par ex. j'utilise la taille du fichier main comme critère ; cf. discussion avec Torukmato, Astronomie et Wallonie (RBOT) ;
- Traiter qu'un petit nombre d'articles par projet pour leur laisser le temps d'évaluer, donc vérifier le nombre d'articles en attente d'évaluation par projet avant d'apposer ^^
- Voir la RBOT sur les paramètres obsolètes de Wikiprojet (ex)
- Éviter les doublons (ex car Optique est une sous-cat de Physique)
- Sinon, ça semble en bonne voie, des encouragements ! LD • m'écrire • 8 juillet 2021 à 01:17 (CEST)
Erreurs ou questions techniques
[modifier | modifier le code]Problème lié aux requêtes 'edit'
[modifier | modifier le code]Salut aux suiveurs de la page, j'ai besoin d'aide. Je code en Python 3.8 et j'utilise la distribution Anaconda3 de l'IDE Spyder4, dont particulièrement la librairie requests pour les requêtes HTTP que je fais. Cuaggbot passe par l'API pour tout ce qu'il est censé faire, et si il réussit à faire une requête 'action=query' sans aucun problème, pour lire les pages, le code que j'utilise pour les requêtes 'action=edit' passe son temps à lever des erreurs qui se déclenchent les unes les autres : dans l'ordre de déclenchement, une ConnectionRefusedError (dont le message explicatif est le suivant : '[WinError 10061] Aucune connexion n’a pu être établie car l’ordinateur cible l’a expressément refusée'), puis une newConnectionError, ensuite une MaxRetryError et une ConnectionError enfin. Je joins la partie problématique du code (les doubles slashs sont des commentaires, donc à remplacer par des #, c'est juste que MediaWiki transforme les # de début de ligne en liste numérotée)
Code
[modifier | modifier le code]import requests, time
# Connexion au compte du bot
S = requests.Session()
URL = "https:#fr.wikipedia.org/w/api.php"
#Login token
PARAMS_0 = {
'action':"query",
'meta':"tokens",
'type':"login|csrf",
'format':"json"
}
R = S.get(url=URL, params=PARAMS_0)
DATA = R.json()
loginToken = DATA['query']['tokens']['logintoken']
print(loginToken)
PARAMS_1 = {
'action':"login",
'lgname':"Cuaggbot",
'lgpassword':"",
'lgtoken':loginToken,
'format':"json"
}
R = S.post(URL, data=PARAMS_1)
PARAMS_2 = {
"action": "query",
"meta": "tokens",
"format": "json"
}
R = S.get(url=URL, params=PARAMS_2)
DATA = R.json()
editToken = DATA['query']['tokens']['csrftoken']
print(editToken)
#Requête de test
time.sleep(10)
PARAMS = {
'action':'edit',
'title':'Utilisateur:Cuaggbot',
'appendtext':'Test',
'bot':True,
'format':'json',
'token':editToken
}
r = S.post(url='https:#fr.wikipedia.fr/w/api.php', params=PARAMS)
print(r.json())
Résolution(s)
[modifier | modifier le code]Proposition de librairie pour se connecter, LD
[modifier | modifier le code]- Autres ressources : here
- cf. code suivant
from pywikiapi import wikipedia
# Connect to French Wikipedia
site = wikipedia('fr')
# Iterate over all query results as they are returned
# from the server, handling continuations automatically.
# (pages whose title begins with "New York-New Jersey")
for r in site.query(list='allpages', apprefix='New York-New Jersey'):
for page in r.allpages:
print(page.title)
# Iterate over two pages, getting the page info and the list of links for each of the two pages. Each page will be yielded as a separate result.
for page in site.query_pages(titles=['Test', 'API'], prop=['links', 'info'], pllimit=10):
print(page.title)
print(', '.join([l.title for l in page.links]))
print()
site.login('username', 'fake password for this page')
site('edit', text=...)
Utilisation
[modifier | modifier le code]J'utilise ça pour me connecter mais je passe mon temps à avoir une erreur quand je run : une APIError, dont le message d'erreur est "The \"token\" parameter must be set.". Pourtant, il est récupéré et placé dans la variable editToken qui s'affiche proprement donc je ne comprends pas pourquoi il ne me le prend pas
import time
from pywikiapi import wikipedia
#Connexion au compte du bot sur cette ligne
site = wikipedia('fr')
# Connexion
editToken = site.token()
print(editToken)
time.sleep(5)
#Test edit
PARAMS = {
'data':{
'title':'Utilisateur:Cuaggbot',
'append':'/',
'format':'json',
'token':editToken
},
}
site('edit', POST=1, HTTPS=1, EXTRAS=PARAMS)
Code de Jules*
[modifier | modifier le code]Je n'ai plus trop la tête dans le code donc pour t'aider à trouver ce qui cloche quand tu essaies de te connecter. Mais si ça peut t'aider, voici mon code (il n'utilise pas la bibliothèque pywikiapi). J'utilise une classe pour la session (elle fait des trucs en plus, donc une partie du code ne t'intéresse pas). — Jules* Discuter 2 juillet 2021 à 12:19 (CEST)
soft_headers = {"User-Agent" : "PyBot de pluie (https://fr.wikipedia.org/wiki/Utilisateur:Bot_de_pluie)"}
class Session():
"""
A class for a session that can interact with the API.
"""
def __init__(self, api_url, bot_username, bot_password):
self.api_url = api_url
self.bot_username = bot_username
self.bot_password = bot_password
#Create Session.
self.session = requests.Session()
def login(self):
"""
Allow user to log in. Returns True if success, False otherwise.
"""
#Get login token
params_0 = {
"action":"query",
"meta":"tokens",
"type":"login",
"format":"json"
}
current_request = self.session.get(url = self.api_url, params = params_0, headers = soft_headers)
current_data = current_request.json()
login_token = current_data["query"]["tokens"]["logintoken"]
#Try to login
params_1 = {
"action":"login",
"lgname": self.bot_username,
"lgpassword": self.bot_password,
"lgtoken": login_token,
"format":"json"
}
current_request = self.session.post(self.api_url, data = params_1, headers=soft_headers)
current_data = current_request.json()
login_result = current_data["login"]["result"]
if login_result == "Success":
addLogLine(self.api_url, "[login success]")
return True
else:
addLogLine(self.api_url, "[login error]")
return False
def logout(self):
"""
Logout from current account.
"""
params_0 = {"action":"logout", "format":"json"}
data = self.session.get(url = self.api_url, params = params_0)
addLogLine(self.api_url, "[logout]")
def getEditToken(self, page_title):
"""
Returns edit_token, last_revision_time, current_time for an asked page_title.
"""
params_0 = {
"action":"query",
"meta":"tokens|userinfo",
"type":"csrf",
"format":"json",
"curtimestamp":"1",
"prop":"revisions",
"rvprop":"timestamp",
"rvslots":"*",
"uiprop":"hasmsg",
"titles": page_title,
"indexpageids":"1"
}
current_request = self.session.get(url= self.api_url, params= params_0, headers=soft_headers)
current_data = current_request.json()
#Check for new message
stop_bot = checkForMessage(current_data)
if stop_bot == True:
addLogLine(self.api_url, "[new_message]")
return "stop"
else:
edit_token = current_data["query"]["tokens"]["csrftoken"]
page_id = current_data["query"]["pageids"][0] #retrieve the page_title id, needed for the next line.
last_revision_time = current_data["query"]["pages"][page_id]["revisions"][0]["timestamp"]
current_time = current_data["curtimestamp"]
return edit_token, last_revision_time, current_time
def edit(self, page_title, new_text, edit_summary, is_minor = 1, is_bot = 1):
"""
Edit a Wikipedia page. Returns True if edit made; returns the error code otherwise ("editconflict", "badtoken"...), or "unknown error". Returns "stop" if bot has a new message.
"""
waiting_time = 5
retry = True
while retry == True:
#1- Get edit token
result_tupple = self.getEditToken(page_title)
try:
edit_token, last_revision_timestamp, current_timestamp = result_tupple
except ValueError: #if ValueError, it means that result_tupple only contain 1 value, which is "stop", because bot has a new message.
return result_tupple
#2- Edit
params_0 = {
"action":"edit",
"format":"json",
"title": page_title,
"text": new_text,
"summary": edit_summary,
"minor": is_minor,
"bot": is_bot,
"token": edit_token,
"basetimestamp": last_revision_timestamp,
"starttimestamp": current_timestamp,
"assert":"user",
"maxlag": 5
}
current_request = self.session.post(self.api_url, data= params_0, headers=soft_headers)
current_data = current_request.json()
try: #try to check for success
edit_result = current_data["edit"]["result"]
if edit_result == "Success":
addEditLog(self.api_url, "[success]", current_data["edit"]["newtimestamp"], page_title, edit_summary) #LOG
retry = False
else:
addEditLog(self.api_url, "[edit not done]", current_data["edit"]["newtimestamp"], page_title, edit_summary) #LOG
return edit_result
except KeyError: #if KeyError:
error_code = handleKeyError(current_data)
addEditLog(self.api_url, "[{}]".format(error_code), "{}".format(current_timestamp), page_title, edit_summary) #LOG
if error_code == "maxlag":
#If too much database replication lag, retry
retry = True
waiting_time*=2 #double the time before retry
addLogLine(self.api_url, "[database replication lag, retrying in {} seconds.]" .format(waiting_time))
time.sleep(waiting_time)
else:
retry = False
return error_code
Et ensuite, le code pour la connexion :
bot_username = ""
bot_password = ""
api_url = "https://test.wikipedia.org/w/api.php"
#login
my_session = Session(api_url, bot_username, bot_password) #create object my_session
is_logged = my_session.login()
if is_logged == True:
print("Connected.")
else:
print(is_logged)
#make an edit
new_text = "This a test : \'\'\'test #5\'\'\'."
edit_summary = "Test #5"
first_edit = my_session.edit(page_title, new_text, edit_summary, is_minor = 1, is_bot = 1)
if first_edit == "Success":
print("Edit published!")
else:
print("ERROR. EDIT NOT PUBLISHED : {}" .format(first_edit))
os.system("pause")
Réponse
[modifier | modifier le code]Ca marche. Yippee-ki-yay, MF, et meci Jules. Je vais lancer le test de l'évaluation projet vers 14h à raison d'une page toutes les 15 secondes. Le projet évalué en premier sera le projet Abbeville, dont (selon éval-portail.js) seuls 52 articles sont à évaluer. Hésitez pas à checker les RC et à bloquer le bot si il fait n'importe quoi
A 14h
[modifier | modifier le code]IL EST VIVAAANNNTTT !!!! IL FAIT CE QU'ON LUI DEMANDE !!!! Je suis joie
En vrai j'ai eu qq problèmes quand il a fallu lui faire créer des PDD inexistantes et il a aussi dupliqué des modèles ou des arguments mais maintenant c'est bon, j'ai toujours réussi à régler ses problèmes et il tourne parfaitement sur son projet.
Formulaire de requête
[modifier | modifier le code]Maintenant que la pose d'un modèle en page de discussion marche, j'aimerais me lancer dans la conception du formulaire mais je n'ai presque aucune compétence en HTML. Mon idée, basée sur ce que j'ai lu vite fait sur la semaine, serait d’utiliser plusieurs éléments Form, dont certains cachés. On commencerait avec la question de base, 'Que voulez-vous que Cuaggbot fasse?', à laquelle serait associée la liste déroulante des options. Ensuite, selon le résultat, on montre le Form qui correspond à la requête, et une fois ce deuxième formulaire validé, on envoie la requête au programme qui gère le bot. Ca c'est la théorie, j'ai déjà une page HTML pas trop loin de ce que je veux, mais le problème c'est qu'elle est statique et que le résultats du premier Form ne sont pas utilisés
Remarques
[modifier | modifier le code]Dans l'idée, j'imagine que tu vois un code-type suivant (rendu):
<form action="/requête" method="post">
<div>
<label for="question">Que voulez-vous que Cuaggbot fasse ?</label><br/>
<SELECT name="Example" size="1">
<OPTION>1
<OPTION>2
<OPTION>3
<OPTION>4
<OPTION>5
</SELECT>
</div>
<div class="button">
<button type="submit">Valider</button>
</div>
</form>
Mais le problème, c'est que le mediawiki aura besoin d'une page spéciale pour faire fonctionner les forms. Le code sera légèrement différent. L'avantage cela dit, c'est que la page spéciale pourra être restreinte qu'à une catégorie d'utilisateurs (par ex. les utilisateurs autopatrolled) en plus de pouvoir lire une autre page de restriction...
Il faudra du html + javascript à mon avis, dans un style comme celui-ci (bon le code n'est pas parfaitement opérationnel c'est une ébauche...) tester
<!DOCTYPE html>
<html lang="fr"
<head>
<meta charset="utf-8">
<title>CHOIX LISTE EN CASACADE</title>
<style>
.selectWrapper{
display:inline-block;
border:1px solid #cccccc;
}
.selectBox{
width:120px;
border:0px;
outline:none;
}
.form-group{
display:block;
vertical-align:middle;
margin:5px;
}
.form-group>span {
display: inline-block;
width:120px !important;
}
.form-vertical{
display: block;
}
</style>
</head>
<body>
<form name="formu" class="form-vertical">
<div class="form-group" id="div_listemaintenance">
<span>Choisir une maintenance</span>
<div class="selectWrapper">
<select name="listemaintenance"
id="listemaintenance"
onChange='filltheselect(this.id, this.value)'
class="selectBox">
</select>
</div>
</div>
<div class="form-group" id="div_listechoix">
<span>Choisir un choix</span>
<div class="selectWrapper">
<select name="listechoix"
id="listechoix"
class="selectBox">
</select>
</div>
</div>
<div class="form-group" id="div_listemotif">
<span>Choisir un motif</span>
<div class="selectWrapper">
<select name="listemotif"
id="listemotif"
class="selectBox">
</select>
</div>
</div>
</form>
</body>
<script type="text/javascript">
var maintenance = [];
var choix=[];
var motif=[];
maintenance[0] = ["p0", "Évaluer"];
maintenance[1] = ["p1", "Modèles"];
// maintenance Évaluer
choix["p0"] = [];
choix["p0"][0] = ["p0v0", "Ajouter un projet"];
choix["p0"][1] = ["p0v1", "Remplacer un projet"];
choix["p0"][2] = ["p0v2", "Retirer un projet"];
//maintenance Modèles
choix["p2"]=[];
choix["p2"][0] = ["p2v0", "Lien"];
choix["p2"][1] = ["p2v1", "Cassini-Ehess"];
choix["p2"][2] = ["p2v2", "Ébauche"];
// maintenance Évaluer
motif["p0"] = [];
motif["p0"][0] = ["p0m0", "France"];
motif["p0"][1] = ["p0m1", "Italie"];
motif["p0"][2] = ["p0m2", "Russie"];
motif["p0"][3] = ["p0m3", "Autre"];
// maintenance Modèles
motif["p1"] = [];
motif["p1"][0] = ["p1m0", "maintenance ref Modèles"];
motif["p1"][1] = ["p1m1", "Ajouter"];
motif["p1"][2] = ["p1m2", "Retirer"];
motif["p1"][3] = ["p1m3", "Substituer"];
// maintenance Autres
motif["p2"] = [];
motif["p2"][0] = ["p1m0", "Example"];
motif["p2"][1] = ["p1m1", "Example"];
//-------------------------------------------------//
// Fonction pour remplir les listes
//-------------------------------------------------//
function init_list(listId,arrayValues){
var liste = document.getElementById(listId);
arrayValues.forEach(function(element) {
var option = document.createElement("option");
option.value = element[0];
option.text = element[1];
liste.add(option);
});
}
//-------------------------------------------------//
// On rempli les listes en fonction du choix
//-------------------------------------------------//
function filltheselect(listeId, choix){
console.log(listeId);
switch (listeId) {
case "listemaintenance":
console.log(choix);
raz("listechoix");
raz("listemotif");
//Si la variable choix a une clé qui existe par rapport au choix
if(typeof(choix[choix]) != "undefined" && choix[choix]!=null){
init_list('listechoix',choix[choix]);
document.getElementById('div_listechoix').style.display = 'block';
}else{
document.getElementById('div_listechoix').style.display = 'none';
}
//Si la variable motif a une clé qui existe par rapport au choix
if(typeof(motif[choix]) != "undefined" && motif[choix]!=null){
init_list('listemotif',motif[choix]);
document.getElementById('div_listemotif').style.display = 'block';
}else{
document.getElementById('div_listemotif').style.display = 'none';
}
break;
}
}
function raz(listeId){
var liste = document.getElementById(listeId);
liste.innerHTML = "";
}
//-------------------------------------------------//
//initialisation des listes
//-------------------------------------------------//
init_list('listemaintenance',maintenance);
init_list('listechoix',choix["p0"]);
init_list('listemotif',motif["p0"]);
</script>
</body>
</html>
J'espère que ça te donne des pistes, LD • m'écrire • 2 juillet 2021 à 18:19 (CEST)