#!/bin/env perl # Copyright (c) 2014, 2015 Daniel Jakots # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. use warnings; use strict; ###################################################################### # this package was created only for checking modified files. If a # # file was modified, append timestamp will be updated, you need to # # have write access to checked file! # ###################################################################### { package check; use strict; use warnings; use File::stat; use Time::localtime; use POSIX qw(strftime); sub fichier { my $file = shift(); my $time; $time = shift() or $time = 10; # if checked file doesn't exist, return 0 unless (-f $file) { return(0); } # init all local variables my $ltime = strftime("%s", @{ localtime() }); my $atime = strftime("%s", @{ localtime(stat($file)->atime) }); my $mtime = strftime("%s", @{ localtime(stat($file)->mtime) }); my $ntime = $mtime-($time+2); # we check if localtime minus modified time is less than configured # time. If it's true, we set a new append/modified time via utime(). if (($ltime-$mtime) <= $time) { utime($ntime, $ntime, $file); return(1); } else { return(0); } } } package MyBot; use base qw( Bot::BasicBot ); binmode STDOUT, ":utf8"; use utf8; # le repectoire des données du bot aka autoconf my $bot_dir = `pwd`; chomp $bot_dir ; $bot_dir .= "/"; my $wrk_dir = "wrk-dir/"; my $dir = $bot_dir.$wrk_dir; # symbol auquel le bot répond my $symbol = "+"; # dictionnaire contenant les regex permettants de trouver les FAI my %regex = ( "apinnet" => "(ap[in]|Poitou|Charente|Rochelle|(Deux[- ])?S[èe]vres?|Vienne|Angoul[eêè]me|Niort|Poitiers)", "aquilenet" => "(aq(ui|n)|Bord(o|e?au)|Landes|Gironde)", "arn" => "(a(lsace|rn)|Stras|Colma)", "auvernet" => "(Auver|Puy[- ](de[- ])D[oô]me|avn)", "cafai" => "(cafai|champagne|ardenn?e)", "faimaison" => "(fma|fail?m|Nantes|Loire[- ]Atlantique)", "fdn" => "f(rench|dn)", "franciliens" => "b(f(ranc|cn)|idf|Paris)", "grifon" => "(grif|rennes|[îi]l?le[- ](et[- ])?vilaine)", "ilico" => "(ilc|ill?[iy][ck])|(Corr?[éêèe][sz])", "illyse" => "(ill?y|ill?i[sz]|lyon|rh[ôo]ne|loire|((st|saint)[- ]etienn?e))", "iloth" => "(ilo|mont?pel|h[ée]rault)", "ldn" => "(l(or|dn)|Nancy|Metz|Moselle|Meuse|Meurthe|Vosges)", "ndn" => "(n(ice|dn)|Antibes|Cannes|Valbonne|Alpes[- ]Maritimes)", "netopi" => "(netopi|Seine[- ](et[- ])?Marne)", "pclight" => "(yonne|beon|cheny|pc[- ]?l)", "rezine" => "(r[eé]z|Isère|Grenoble)", "rhizome" => "(rh?[iy][sz]om|Oise|Compi[eéêè]gne)", "sames" => "sam|(Pyrénées[- ]Atlantiques)", "sdn" => "(s(all|dn)|Savoie|Haute[- ]Savoie)", "teleragno" => "(mars|telerag|telegrano)", "tetaneutral" => "(t(eta|tn|nn)|Toulouse|Comminges|(Haute[- ]Garon?ne))", "ail-network" => "a(il|utan)", "chaul-hertz" => "(c(haul|hz)|hertz|tarn)", "igwan" => "(ig[wn]|sbg|saint[- ]barth)", "neutrinet" => "(neutri|n[tre]n|belgique)", "ffdn" => "f(ede|fdn|rance|édé)", "tdn" => "(t(dn|ouraine)|centre|rouvr)", ); # Lis le fichier contenant les infos d'un FAI sub info { my $fai = shift @_; my $filename = $dir.$fai.".info"; if (-e $filename) { my $fh; open ($fh, '<', $filename) or die "Impossible d'ouvrir le fichier $filename en lecture"; while (my $line = <$fh>) { return $line; } close $fh; } else { return "pas d'information pour ". $fai ."\n"; } } # Lis le fichier contenant les nombres adh/abo d'un FAI sub adh { my $fai = shift @_; my $filename = $dir.$fai.".adh"; if (-e $filename) { my $fh; open ($fh, '<', $filename) or die "Impossible d'ouvrir le fichier $filename en lecture"; while (my $line = <$fh>) { return $line; } close $fh; } else { return "pas d'information pour ". $fai ."\n"; } } # lis le fichier et retourne le contenu sub lecture_fichier { my $fichier = shift @_; my $filename = $dir.$fichier; if (-e $filename) { my $fh; open ($fh, '<', $filename) or die "Impossible d'ouvrir le fichier $filename en lecture"; while (my $line = <$fh>) { return $line; } close $fh; } else { return "Nope\n"; } } # on compte le nombre d'adh et d'abo pour la fédé sub adh_abo_ffdn { my $filename = $dir."ffdn.adh"; if (-e $filename) { my $fh; open ($fh, '<', $filename) or die "Impossible d'ouvrir le fichier $filename en lecture"; while (my $line = <$fh>) { return $line; } close $fh; } else { return "pas d'information\n"; } } # on note les RP sub rp { my $link = shift @_; my $filename = "/usr/share/nginx/www/rp.txt"; my $filehandle; open ($filehandle, '>>', $filename) or die "Impossible d'ouvrir le fichier $filename en écriture"; print $filehandle "$link\n"; close $filehandle; return "Une nouvelle RP à traiter est disponible à http://unefede.fdn.fr/rp.txt (hl quota_atypique taziden)"; } sub get_fai { my ($commande, $message) = @_; my @fai_trouves = grep { $message =~ /$regex{$_}/ } keys %regex; if (@fai_trouves < 1 ) { return "commande : ".$symbol."$commande (".$symbol."liste pour avoir la liste) ou ".$symbol."$commande "; } elsif (@fai_trouves > 1 ) { return "Trop de fai trouvés : " . join ', ', @fai_trouves; } else { if ($commande eq 'info') { info $fai_trouves[0]; } elsif ($commande eq 'adh') { adh $fai_trouves[0]; } } } ## Le bot lit le chan et réagit sub said { my ($self, $message) = @_; # check if file was modified. if true we print this file when one user do # something on the chan. if (check::fichier("wrk-dir/suivi", 60)) { return("Il y a du nouveau pour la réunion de suivi. " . lecture_fichier("suivi")); } # si on veut des info if ($message->{body} =~ /^\Q$symbol\Einfo/) { shift @_; if($message->{body} =~ /$regex{"ffdn"}/i) { return "La fédération FDN regroupe des Fournisseurs d'Accès à Internet associatifs se reconnaissant dans des valeurs communes : bénévolat, solidarité, fonctionnement démocratique et à but non lucratif; défense et promotion de la neutralité du Net."; } get_fai 'info', $message->{body}; } # si on veut le nombre d'adhérent elsif ($message->{body} =~ /^\Q$symbol\Eadh/) { shift @_; get_fai 'adh', $message->{body}; } # si on veut de l'aide elsif ($message->{body} =~ /^\Q$symbol\Ehelp/) { return "commandes gérées : ".$symbol."liste, ".$symbol."info, ".$symbol."adh, ".$symbol."suivi, ".$symbol."vote, ".$symbol."source, ".$symbol."ag, ".$symbol."json, ".$symbol."rp"; } # les sources du bot elsif ($message->{body} =~ /^\Q$symbol\Esource/) { lecture_fichier("source"); } # les infos par rapport aux réunions de suivies elsif ($message->{body} =~ /^\Q$symbol\Esuivi/) { lecture_fichier("suivi"); } # les infos par rapport aux réunions de suivies elsif ($message->{body} =~ /^\Q$symbol\Evote/) { lecture_fichier("vote"); } # les infos par rapport à l'ag de la fédé elsif ($message->{body} =~ /^\Q$symbol\Eag/) { lecture_fichier("ag"); } # les infos par rapport au source du bot elsif ($message->{body} =~ /^\Q$symbol\Ejson/) { lecture_fichier("json"); } elsif ($message->{body} =~ /^\Q$symbol\Eliste/) { return "Les associations surveillées (par mes petits yeux de bot) sont : Ail-network, Apinnet, Aquilenet, ARN, Auvernet, CAFAI, Chaul-Hertz, FAImaison, FDN, Franciliens.net, GRIFON, Igwan, Ilico, Illyse, Iloth, LDN, NDN, Neutrinet, PC Light, Rezine, Rhizome, Sames Wireless, Teleragno, TDN et Tetaneutral"; } # on assiste ceux qui ont alzheimer :p elsif ($message->{"body"} =~ /^symbol/) { return "Les symboles sont : pour UnRouteur : > ; pour moi-même : $symbol"; } # easter egg elsif ($message->{body} =~ /datafoin/) { my $de = int rand(5); if ($de==1) { return "il ne faut pas me donner à manger après minuit /o\\"; } elsif($de==2){ return "omnomnom"; } elsif($de==3){ return "mais je vais grossir /o\\"; } elsif($de==4){ return "vouiii"; } elsif($de==5){ return "datafoin <3"; } } elsif ($message->{body} =~ /^\Q$symbol\Erp/) { my $url = $message->{body}; $url =~ s/^\Q$symbol\Erp //; rp($url); } } # tout ce qu'on écrit dans le ficher log apparait dans $channel sub connected { my $fichier = $dir."log"; my $self = shift; $self->forkit({ channel => "#ffdn", run => [ qw( /usr/bin/tail -f -n0 /home/bot/bot-irc/wrk-dir/log ) ], }); } # aucune idée de comment on déclenche cette ligne sub help { "Je suis le bot de la fédé." } #Info de connexion du bot MyBot->new( server => 'irc.geeknode.org', channels => [ '#fdn', '#ffdn', '#franciliens.net', '#faimaison', '#illyse'], nick => 'UneFede', username => 'bot', name => 'Droide de la Federation FDN, run by Vigdis' )->run();