| Démarrer |
|
|
|
|
|
|
|
| Scripting TCL |
|
|
|
|
| Eggdrop 1.7 |
|
|
| Botnet |
|
|
| Divers |
|
|
|
| Aide |
|
|
|
|
|
|
|
|
|
[ Exercices corrigés de TCL ]
[ Sommaire ]
[ Exercice 1 ]
Exercice proposé par Lucas Nussbaum
Ce premier exercice vous permettra de créer un script très simple.
Avec ce script, le bot doit :
- Dire "bonjour nickname" sur le channel quand nickname entre sur le channel.
- Envoyer une notice à nickname quand il rentre sur le channel, en disant "Salut, je suis nick du bot, le bot de nom du channel. Pour avoir plus d'infos sur moi, tape !eggfrrocks sur nom du channel !"
- Lorsque nickname tape !eggfrrocks (le nom de la commande peut être changé ;) ), le bot doit lui envoyer un message privé (en query, private, pv, etc ...), c'est-à-dire un PRIVMSG, avec pour texte "Désolé, mon maître n'a pas encore fait l'exercice 2 :("
A vos claviers !
Voir le corrigé de cet exercice
[ Exercice 2 ]
Exercice proposé par Seven
Qui n'a jamais rêvé de lire une ligne au hasard dans un fichier texte ?
Qui n'a jamais rêvé de ces mondes souterrains, de ces mers lointaines peuplées de légendes, où d'une richesse soudaine qui se conquerrait au détour d'un chemin de la Cordillère des Andes ?
Euhh non aucun rapport...
Enfin bref comment lire dans un fichier texte ?
Et comment lire une ligne au hasard et l'afficher sur le channel ?
A quoi ca peut bien servir, aucune idée, on verra plus tard...
Let's go...
Faites un script qui, lorsqu'un utilisateur tape !pouet sur un channel, fait dire au bot une phrase au hasard trouvée dans un fichier texte.
Voir le corrigé de cet exercice
[ Corrigé de l'exercice 1 ]
Si vous n'avez pas réussi à faire ce script facile, vous devriez relire l'initiation au TCL.
Comme c'est peut-être votre premier script, nous allons le corriger pas à pas.
Dire "bonjour nickname" sur le channel quand nickname entre sur le channel.
Pour détecter l'entrée de quelqu'un sur le channel, il faut utiliser un bind. Les binds sont décrits dans le fichier doc/tcl-commands.doc (à ouvrir avec le bloc-notes sous Windows). Un survol de ce fichier vous fera le plus grand bien, histoire de savoir ce dont l'eggdrop est capable !
Voici ce qu'on trouve sur le bind JOIN dans ce fichier :
(8) JOIN (stackable)
bind join <flags> <mask> <proc>
procname <nick> <user@host> <handle> <channel>
Description: triggered by someone joining the channel. The mask in
the bind is matched against "#channel nick!user@host" and can
contain wildcards.
Module: irc
Pour exécuter une procédure lorsque quelqu'un arrive sur un channel, il faut donc écrire :
bind join - * join:exo1
proc join:exo1 { nick uhost hand chan } {
code de la procédure
}
Si le but est de détecter les JOINs sur #test, et pas sur les autres channels :
bind join - "#test *" join:exo1
proc join:exo1 { nick uhost hand chan } {
code de la procédure
}
Ensuite, il faut envoyer un message sur le channel. Pour envoyer un message au serveur, il faut utiliser puthelp, putserv ou putquick. La différence entre ces trois commandes est la file d'attente où est mis le message. putquick envoie dans la file la plus prioritaire, tandis que puthelp envoie dans la file la moins prioritaire.
Pour envoyer un message :
putserv "PRIVMSG $chan :texte"
Attention, il ne faut pas oublier le ":".
Notre script devient donc :
bind join - "#test *" join:exo1
proc join:exo1 { nick uhost hand chan } {
putserv "PRIVMSG $chan :Bonjour $nick"
}
Envoyer une notice à nickname quand il rentre sur le channel, en disant "Salut, je suis nick du bot, le bot de nom du channel. Pour avoir plus d'infos sur moi, tape !eggfrrocks sur nom du channel !"
Cette partie du problème est peu différente de la précédente. Pour afficher le nick du bot, il faut utiliser la variable botnick, sans oublier de la mettre en global dans la procédure :
bind join - "#test *" join2:exo1
proc join2:exo1 { nick uhost hand chan } {
global botnick
putserv "NOTICE $nick :Salut, je suis $botnick, le bot de $chan. Pour avoir plus d'infos sur moi, tape !eggfrrocks sur $chan !"
}
Mais il est bien sûr possible de combiner cette procédure avec la précédente :
bind join - "#test *" join:exo1
proc join:exo1 { nick uhost hand chan } {
global botnick
putserv "PRIVMSG $chan :Bonjour $nick"
putserv "NOTICE $nick :Salut, je suis $botnick, le bot de $chan. Pour avoir plus d'infos sur moi, tape !eggfrrocks sur $chan !"
}
Lorsque nickname tape !eggfrrocks (le nom de la commande peut être changé ;) ), le bot doit lui envoyer un message privé (en query, private, pv, etc ...), c'est-à-dire un PRIVMSG, avec pour texte "Désolé, mon maître n'a pas encore fait l'exercice 2 :("
La seule différence avec la partie précédente est l'utilisation d'un bind différent. Ici, il faut utiliser le bind PUB. On fait aussi un test pour vérifier le channel sur lequel a été utilisée la commande.
bind pub - !eggfrrocks pub:exo1
proc pub:exo1 { nick uhost hand chan text } {
if ![string compare [string tolower $chan] "#test"] {
putserv "PRIVMSG $nick :Désolé, mon maître n'a pas encore fait l'exercice 2 :("
}
}
Quand vous testerez ce script, vous vous rendrez compte que le bind JOIN permet au bot de détecter son propre join. Il va donc se parler à lui même ... pas très sérieux ! Pour corriger ce comportement, vérifiez que le nick ayant rejoint n'est pas celui du bot :
bind join - "#test *" join:exo1
proc join:exo1 { nick uhost hand chan } {
global botnick
if ![string compare $botnick $nick] return
putserv "PRIVMSG $chan :Bonjour $nick"
putserv "NOTICE $nick :Salut, je suis $botnick, le bot de $chan. Pour avoir plus d'infos sur moi, tape !eggfrrocks sur $chan !"
}
Voila, j'espère que vous avez tout compris, sinon n'hésitez pas à poser des questions, par exemple sur le forum.
[ Corrigé de l'exercice 2 ]
Déjà et si on commençait par l'ouvrir ce fichier texte hein ?
On ouvre un fichier avec la commande 'open', cette commande peut ouvrir un fichier ou un port serie (entre autre). La syntaxe habituelle est 'open nom_fichier type_acces', cette fonction retourne un identifieur du genre filef97ed8, c'est ce qui nous permettra d'acceder au fichier plus tard.
On peut ouvrir un fichier en lecture et/ou écriture, voici les différents type d'accés :
- r : ouvre le fichier en lecture seulement, le fichier doit déjà exister.
- r+ : ouvre le fichier en lecture et écriture, le fichier doit déjà exister.
- w : ouvre le fichier en écriture seulement, il le remet à 0 si il existe déjà sinon il crée un nouveau fichier
- w+ : ouvre le fichier en lecture et écriture, il le remet à 0 si il existe déjà sinon il crée un nouveau fichier
- a : ouvre le fichier en écriture seulement, crée un nouveau fichier vide s'il n'existe pas, se positionne à la fin du fichier.
- a+ : ouvre le fichier en lecture et écriture, crée un nouveau fichier vide s'il n'existe pas, se positionne à la fin du fichier.
Un fichier ouvert avec 'open' doit toujours être refermé avec la commande 'close' suivie de l'identifieur du fichier.
Une fois le fichier ouvert, on peut lire une ligne avec la commande 'gets' (toujours suivie de l'identifieur du fichier), après un 'gets' l'identificateur du fichier pointe sur la ligne suivante, ce qui fait qu'au prochain 'gets' on lira la ligne d'aprés et non pas la même ligne, c'est toujours bon à savoir.
Bon du coup on pourrait faire des 'gets' à l'infini si on n'avait pas un moyen de savoir si on est à la fin du fichier ou pas, la fin du fichier ou End Of File (eof) est detectée grace à la commande tcl 'eof' suivie, comme d'habitude, par l'identificateur du fichier.
Mais mettons ces fonctions en application parce que ça n'a pas dû bien imprimer :
proc fichier:lis_ligne { fichier num_ligne } {
#On verifie d'abord si le fichier est lisible ca evitera des erreurs...
#On ne va pas utiliser la commande 'error' pour simplifier les choses...
if { ![file readable $fichier] } { return "erreur: fichier non lisible" }
#On va juste verifier que le numero de ligne semble correct...
#On ne va toujours pas utiliser la commande 'error' pour simplifier les choses...
if { $num_ligne<=0 } { return "erreur: numéro de ligne non valide" }
#On ouvre le fichier en lecture seulement
set fHnd [open $fichier "r"]
#Voila maintenant on peut lire ou on veut :)
set counter 0 ;# Notre compteur de lignes
set ligne "" ;# Notre ligne lu
#Tant que on n'est pas a la fin du fichier...
while { ![eof $fHnd] } {
#On lit la ligne courante.
set foo [gets $fHnd]
#On augmente le compteur pour savoir a quelle ligne nous en sommes.
incr counter
#Si c'est le bon numero de ligne, on met à jour la variable et on sort du while
if { $counter == $num_ligne } {
set ligne $foo
break
}
}
#On libére le fichier
close $fHnd
#Et on retourne la ligne...
return $ligne
}
Bon jusque là tout va bien, mais je suppose qu'a un moment donné vous allez vouloir lire une ligne au hasard dans le fichier texte, et pour cela il faudrait savoir combien il a de lignes...
.. et bien c'est presque pareil que la fonction d'avant, à peu de choses près.
proc fichier:combien_de_lignes { fichier } {
#On verifie d'abord si le fichier est lisible ca evitera des erreurs...
#On ne va pas utiliser la commande 'error' pour simplifier les choses...
if { ![file readable $fichier] } { return 0 }
#On ouvre le fichier en lecture seulement
set fHnd [open $fichier "r"]
#Voila maintenant on peut lire ou on veut :)
set counter 0 ;# Notre compteur de lignes
#Tant que on n'est pas a la fin du fichier...
while { ![eof $fHnd] } {
#On lit la ligne courante.
gets $fHnd
#On augmente le compteur pour savoir a quelle ligne nous en sommes.
incr counter
}
#On libére le fichier
close $fHnd
#Et on retourne le nombre de lignes...
return $counter
}
Et voilà, repassez vous le truc au ralenti, ca donne bien le nombre de lignes ;)
Et maintenant si on fait un petit mélange avec l'exercice numéro 1...
bind pub - !pouet pub:exo2
proc pub:exo2 { nick uhost hand chan text } {
#Notre petit fichier
set fichier "toto.txt"
#Combien a t-on de lignes ?
set nb_lignes [fichier:combien_de_lignes $fichier]
#Prenons un chiffre au hasard entre 1 et nb_lignes, je n'expliquerai pas cette ligne aujourd'hui.
#Des petits malins vous diront qu'il existe la fonction rand fournie par eggdrop, mais bon,
#comment feriez vous en tcl pur alors ?
set num_hasard [expr int(rand()*$nb_lignes)+(1&&$nb_lignes)]
#Hop on recupere notre ligne
set ligne [fichier:lis_ligne $fichier $num_hasard]
#Et on l'affiche sur le channel...
putserv "PRIVMSG $chan :$ligne"
#Que du bonheur!
}
Maintenant si on suppose que le fichier toto.txt contient :
"Toi même!"
"A tes souhaits!"
"Mais oui mais oui..."
Quelqu'un tape !pouet sur le channel...
- nb_lignes va valoir 3
- num_hasard pourrait valoir 2
- du coup ligne va valoir "A tes souhaits!"
Et voila ce qu'on verra sur le chan :
!pouet
A tes souhaits!
Je vous laisse imaginer les petits trucs que vous pouvez faire : tamére, blagues, citations, etc...
Là, tcl commence tout de suite à devenir plus drôle non ?
Have fun.
Auteur original : Lucas Nussbaum et Seven
Copyright (c) 2002 Lucas Nussbaum et Seven
Ce document issu de Eggdrop-fr.org est soumis à la licence GNU FDL. Permission vous est donnée de copier, distribuer, et/ou modifier des copies de ce document sous les termes de
la licence GNU Free Documentation Licence, version 1.1 ou ultérieure publiée par la Free Software Foundation.
|
|