Mettre un antiflood sur une commande
Vous aurez également besoin de la procédure
utimerexists, qui permet de vérifier l'existence d'un utimer et de retourner son ID.
Déclaration des variables
# Activer l'antiflood ? (0 = désactivé / 1 = activé)
variable antiflood 1
# Contrôle de flood individuel.
# Lorsqu'il s'active, la commande sera bloquée pour l'utilisateur qui l'a
# déclenché uniquement.
# Exemple : "10:600" = 10 requêtes maximum en 600 secondes, les suivantes seront
# ignorées.
# Seuil pour la commande !MaCommande1 :
variable MaCommande1_flood_limit "10:600"
# Seuil pour la commande !MaCommande2 :
variable MaCommande2_flood_limit "5:120"
# Seuil pour la commande !MaCommande3 :
variable MaCommande3_flood_limit "2:180"
# Contrôle de flood global, toutes commandes confondues.
# Lorsqu'il s'active, les commandes du script sont bloquées pour tout le monde
# sur le chan concerné.
# Remarque : pour le nombre de requêtes, spécifiez une valeur supérieure à la
# plus grande valeur définie pour le contrôle de flood individuel.
variable global_flood_limit "20:600"
# Intervalle de temps minimum entre l'affichage de 2 messages avertissant que
# l'antiflood a été déclenché (ne réglez pas cette valeur trop bas afin de ne
# pas être floodé par les messages d'avertissement de l'antiflood...)
variable antiflood_msg_interval 60
# Mode d'affichage préféré pour les messages de l'antiflood.
# (1 = message public / 2 = notice à l'utilisateur)
variable preferred_display_mode 1
A placer au début de la procédure appelée par la commande à contrôler
proc procedure_appelee_par_MaCommande1 {nick host hand chan arg} {
variable antiflood
variable MaCommande1_flood_limit
variable global_flood_limit
if {
(($antiflood == 1)
&& (([antiflood $nick $chan "nick" !MaCommande1 $MaCommande1_flood_limit])
|| ([antiflood $nick $chan "chan" "*" $global_flood_limit])))
} then {
return
} else {
*reste du code de la procédure*
}
}
Procédures de l'antiflood
###############################################################################
### Contrôle du flood.
### - focus peut valoir "chan" ou "nick" et différenciera un contrôle de flood
### collectif où les commandes seront bloquées pour tout le monde, d'un
### contrôle individuel où les commandes seront bloquées pour un seul individu.
### - command peut valoir "*" ou le nom d'une commande et différenciera un
### contrôle par commande ou toutes commandes du script confondues.
### - limit est exprimé sous la forme "xx:yy", où xx = nombre maximum de
### requêtes et yy = durée d'une instance.
###############################################################################
proc antiflood {nick chan focus command limit} {
variable antiflood_instances
variable antiflood_msg
variable antiflood_msg_interval
variable preferred_display_mode
lassign [split $limit ":"] max_instances instance_length
if { $focus eq "chan" } {
set hash [md5 "$chan,$command"]
} else {
set hash [md5 "$nick,$chan,$command"]
}
# L'antiflood est dans un statut neutre, on l'initialise.
if { ![::tcl::info::exists antiflood_instances($hash)] } {
set antiflood_instances($hash) 0
set antiflood_msg($hash) 0
}
if { $antiflood_instances($hash) >= $max_instances } {
if { $preferred_display_mode == 1 } {
set output_method "PRIVMSG"
set output_target $chan
} else {
set output_method "NOTICE"
set output_target $nick
}
if { !$antiflood_msg($hash) } {
set antiflood_msg($hash) 2
if { $command eq "*" } {
if { $focus eq "chan" } {
puthelp "PRIVMSG $chan :\00304:::\003 \00314Contrôle de flood activé pour toutes les commandes du script : pas plus de $max_instances requête(s) toutes les $instance_length seconde(s).\003"
} else {
puthelp "PRIVMSG $chan :\00304:::\003 \00314Contrôle de flood activé pour $nick sur toutes les commandes du script : pas plus de $max_instances requête(s) toutes les $instance_length seconde(s).\003"
}
} else {
if { $focus eq "chan" } {
puthelp "$output_method $output_target :\00304:::\003 \00314Contrôle de flood activé pour la commande \"$command\" : pas plus de $max_instances requête(s) toutes les $instance_length seconde(s).\003"
} else {
puthelp "$output_method $output_target :\00304:::\003 \00314Contrôle de flood activé pour $nick sur la commande \"$command\" : pas plus de $max_instances requête(s) toutes les $instance_length seconde(s).\003"
}
}
if { [set msgresettimer [utimerexists "antiflood_msg_reset $hash"]] ne ""} {
killutimer $msgresettimer
}
utimer $antiflood_msg_interval [list antiflood_msg_reset $hash]
} elseif { $antiflood_msg($hash) == 1 } {
set antiflood_msg($hash) 2
if { $command eq "*" } {
puthelp "PRIVMSG $chan :\00304:::\003 \00314Le contrôle de flood est toujours actif, merci de patienter.\003"
} else {
puthelp "$output_method $output_target :\00304:::\003 \00314Le contrôle de flood est toujours actif, merci de patienter.\003"
}
if { [set msgresettimer [utimerexists "antiflood_msg_reset $hash"]] ne ""} {
killutimer $msgresettimer
}
utimer $antiflood_msg_interval [list antiflood_msg_reset $hash]
}
return 1
} else {
incr antiflood_instances($hash) 1
utimer $instance_length [list antiflood_close_instance $hash]
return 0
}
}
###############################################################################
### Fermeture d'une instance de l'antiflood.
###############################################################################
proc antiflood_close_instance {hash} {
variable antiflood_instances
variable antiflood_msg
incr antiflood_instances($hash) -1
# si le nombre d'instances retombe à 0, on efface les variables instance et
# antiflood_msg afin de ne pas encombrer la mémoire inutilement
if { $antiflood_instances($hash) == 0 } {
unset antiflood_instances($hash)
unset antiflood_msg($hash)
# le nombre d'instances est retombé en dessous du seuil critique, on
# réinitialise antiflood_msg
} else {
set antiflood_msg($hash) 0
if { [set msgresettimer [utimerexists "antiflood_msg_reset $hash"]] ne ""} {
killutimer $msgresettimer
}
}
return
}
###############################################################################
### Réinitialisation de l'état du message d'avertissement de l'antiflood.
###############################################################################
proc antiflood_msg_reset {hash} {
variable antiflood_msg
set antiflood_msg($hash) 1
return
}