Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

BOT IRC : GÉNÉRATEURS DE LOGS AU FORMAT MIRC


Information sur la source

Catégorie :Class et Objet ( POO ) Classé sous : irc, bot, mirc, log Niveau : Initié Date de création : 02/07/2008 Date de mise à jour : 02/07/2008 13:28:29 Vu : 1 484

Note :
7 / 10 - par 1 personne
7,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (6)
Ajouter un commentaire et/ou une note

Description

A défaut de trouver un service ou un bot qui pouvait me générer des logs pour pisg et en lançant un petit défit à Yling sur le chan tout à l'heure, j'ai entrepris de coder un bot en php qui générait un log au format mirc.

Quand on comprends comment fonctionne un serveur irc, ça devient tout de suite facile de faire des trucs sympa ^^

Pour l'instant, ça donne : http://irc.deblan.fr/stats.html et c'est régénéré toutes les 2 minutes (crontab).

Voila la source du bot qui par ailleurs sera amélioré afin de fournir aux deblaneurs des services comme un agrégateur de flux rss, un service d'envoi de mails ou pourquoi pas une cafetière ?!

http://blog.deblan.fr/Billet/Enfin-les-stats-irc-0193/
 

Source

  • !/usr/bin/php5
  • <?php
  • class Irc_log {
  • public $serveur;
  • public $port;
  • public $salon;
  • private $connexion;
  • private $flog_file;
  • public $host;
  • public $nick;
  • public $name;
  • public $irc_log_cfg = array();
  • public function __construct($serveur='localhost', $port=6667, $salon='#general') {
  • $this->serveur = $serveur;
  • $this->port = $port;
  • $this->salon = $salon;
  • $this->flog_file = null;
  • $this->irc_log_cfg = array(
  • 'log_file_dir' => '',
  • 'log_file_name' => 'log_irc.txt',
  • 'max_log_line' => 1000,
  • 'nick' => 'DebStats',
  • 'host' => 'localhost',
  • 'mail' => 'simon@deblan.fr'
  • );
  • }
  • public function __set($name, $value) {
  • if(isset($this->irc_log_cfg[$name])) {
  • $this->irc_log_cfg[$name] = $value;
  • }
  • }
  • public function __get($name) {
  • if(isset($this->irc_log_cfg[$name])) {
  • return $this->irc_log_cfg[$name];
  • }
  • }
  • private function canUseIrc_log() {
  • $possible = true;
  • if(!function_exists('fsockopen')) $possible = false;
  • if(!function_exists('fwrite')) $possible = false;
  • if(!function_exists('feof')) $possible = false;
  • if(!function_exists('fgets')) $possible = false;
  • return $possible;
  • }
  • private function getNumberLogLine() {
  • if(file_exists($this->log_file_dir.'/'.$this->log_file_name)) {
  • if(is_readable($this->log_file_dir.'/'.$this->log_file_name)) {
  • return count(file($this->log_file_dir.'/'.$this->log_file_name));
  • } else {
  • return 0;
  • }
  • } else {
  • return 0;
  • }
  • }
  • private function openLogFile() {
  • if( file_exists($this->log_file_dir.'/'.$this->log_file_name)) {
  • if(!is_readable($this->log_file_dir.'/'.$this->log_file_name)) {
  • die('Le fichier de log n\'est pas lisible ! '.$e->getMessage());
  • }
  • }
  • try {
  • $this->flog_file = fopen($this->log_file_dir.'/'.$this->log_file_name, 'a+');
  • } catch (Exception $e) {
  • die('Ouverture du fichier de log impossible ! '.$e->getMessage()."\r\n");
  • }
  • }
  • public function connexion() {
  • if($this->canUseIrc_log()) {
  • try {
  • $this->openLogFile();
  • $this->connexion = fsockopen($this->serveur, $this->port, $errno, $errstr, 30);
  • fwrite($this->connexion, 'USER '.$this->irc_log_cfg['nick'].' '.$this->irc_log_cfg['host'].' '.$this->irc_log_cfg['mail'].' '.$this->irc_log_cfg['nick']."\r\n");
  • fwrite($this->connexion, 'NICK '.$this->irc_log_cfg['nick']."\r\n");
  • fwrite($this->connexion, 'JOIN '.$this->irc_log_cfg['salon']."\r\n");
  • while (!feof($this->connexion)) {
  • $line = fgets($this->connexion, 1024);
  • echo $line;
  • $this->ananlyseLine($line);
  • }
  • } catch (Exception $e) {
  • die('Connexion au serveur impossible ! '.$errstr()."\r\n");
  • }
  • } else {
  • die('Irc_log ne peut pas se lancer !'."\r\n");
  • }
  • }
  • private function ananlyseLine($line) {
  • if(preg_match('`^PING`', $line)) {
  • $explode = explode(' ', $line);
  • $this->pong($explode[1]);
  • } else {
  • preg_match("`^:([^!]+)!([^ ]+) *([^ ]+) *([^ ]+) *:`isU", $line, $infos);
  • if(count($infos) > 1) {
  • $infos[5] = str_replace($infos[0], '', $line);
  • $log_line = '';
  • switch($infos[3]) {
  • case 'PRIVMSG':
  • $explode = explode(' ', trim($infos[5]));
  • if(ereg('ACTION', $explode[0])) {
  • $log_line = $this->userAction($infos[1], implode(' ', $explode));
  • } else {
  • $log_line = $this->userMessage($infos[1], implode(' ', $explode));
  • }
  • ;break;
  • case 'NOTICE':
  • $this->sendNotice($infos[1]);
  • ;break;
  • }
  • $this->updateLogs($log_line);
  • }
  • }
  • }
  • private function getTime() {
  • return date('[H:i]', time());
  • }
  • private function userAction($user, $action) {
  • return $this->getTime().' * '.$user.' '.str_replace('ACTION', '', $action)."\r\n";
  • }
  • private function userMessage($user, $message) {
  • return $this->getTime().' <'.$user.'> '.$message."\r\n";
  • }
  • private function pong($ping) {
  • fwrite($this->connexion, 'PONG '.$ping);
  • }
  • private function sendNotice($nick) {
  • fwrite($this->connexion, 'NOTICE '.$nick.' Pas de notice pour les bots...'."\r\n");
  • }
  • private function updateLogs($log_line) {
  • if(mt_rand(0, 10) > 7) {
  • if($this->getNumberLogLine() >= $this->max_log_line) {
  • unlink($this->max_log_line);
  • $this->openLogFile();
  • }
  • }
  • fwrite($this->flog_file, $log_line);
  • }
  • }
  • $irc = new Irc_log($serveur='deblan.fr', $port=6667, $salon='#general');
  • $irc->log_file_dir = '/var/www/web/public/irc.deblan.fr/public_html/';
  • $irc->log_file_name = 'log_irc.txt';
  • $irc->max_log_line = 1000;
  • $irc->nick = 'DebStats';
  • $irc->host = 'localhost';
  • $irc->mail = 'simon@deblan.fr';
  • $irc->connexion();
  • ?>
!/usr/bin/php5
<?php

class Irc_log {
  public $serveur;
  public $port;
  public $salon;
  
  private $connexion;
  private $flog_file;
  
  public $host;
  public $nick;
  public $name;
  
  public $irc_log_cfg = array();

  public function __construct($serveur='localhost', $port=6667, $salon='#general') {
    $this->serveur = $serveur;
    $this->port = $port;
    $this->salon = $salon;
    $this->flog_file = null;    
    
    $this->irc_log_cfg = array(
      'log_file_dir'  => '', 
      'log_file_name' => 'log_irc.txt',
      'max_log_line'  => 1000,
      'nick'          => 'DebStats',
      'host'          => 'localhost',
      'mail'          => 'simon@deblan.fr'
    );    
  }
  
  public function __set($name, $value) {
    if(isset($this->irc_log_cfg[$name])) {
      $this->irc_log_cfg[$name] = $value;
    }
  }
      
  public function __get($name) {
    if(isset($this->irc_log_cfg[$name])) {
      return $this->irc_log_cfg[$name];
    }
  }
  
  private function canUseIrc_log() {
    $possible = true;
    if(!function_exists('fsockopen')) $possible = false;
    if(!function_exists('fwrite'))    $possible = false;
    if(!function_exists('feof'))      $possible = false;
    if(!function_exists('fgets'))     $possible = false;
    return $possible;
  }
  
  private function getNumberLogLine() {
    if(file_exists($this->log_file_dir.'/'.$this->log_file_name)) {
      if(is_readable($this->log_file_dir.'/'.$this->log_file_name)) {
        return count(file($this->log_file_dir.'/'.$this->log_file_name));
      } else {
        return 0;
      }
    } else {
      return 0;
    }
  }
  
  private function openLogFile() {
    if( file_exists($this->log_file_dir.'/'.$this->log_file_name)) {
      if(!is_readable($this->log_file_dir.'/'.$this->log_file_name)) {
        die('Le fichier de log n\'est pas lisible ! '.$e->getMessage());
      }
    }
    try {
      $this->flog_file = fopen($this->log_file_dir.'/'.$this->log_file_name, 'a+');
    } catch (Exception $e) {
      die('Ouverture du fichier de log impossible ! '.$e->getMessage()."\r\n");
    }
  }
  
  public function connexion() {
    if($this->canUseIrc_log()) {
      try {
        $this->openLogFile();
        $this->connexion = fsockopen($this->serveur, $this->port, $errno, $errstr, 30);
        
        fwrite($this->connexion, 'USER '.$this->irc_log_cfg['nick'].' '.$this->irc_log_cfg['host'].' '.$this->irc_log_cfg['mail'].' '.$this->irc_log_cfg['nick']."\r\n");
        fwrite($this->connexion, 'NICK '.$this->irc_log_cfg['nick']."\r\n");
        fwrite($this->connexion, 'JOIN '.$this->irc_log_cfg['salon']."\r\n");
        
        while (!feof($this->connexion)) {
          $line = fgets($this->connexion, 1024);
          echo $line;
          $this->ananlyseLine($line);
        }
        
      } catch (Exception $e) {
         die('Connexion au serveur impossible ! '.$errstr()."\r\n");
      }
    } else {
      die('Irc_log ne peut pas se lancer !'."\r\n");
    }
  }
  
  
  private function ananlyseLine($line) {
    if(preg_match('`^PING`', $line)) {
      $explode = explode(' ', $line);
      $this->pong($explode[1]);
    } else {
      preg_match("`^:([^!]+)!([^ ]+) *([^ ]+) *([^ ]+) *:`isU", $line, $infos);
      if(count($infos) > 1) {
        $infos[5] = str_replace($infos[0], '', $line);
        $log_line = '';
        switch($infos[3]) {
          case 'PRIVMSG':
            $explode = explode(' ', trim($infos[5]));
            if(ereg('ACTION', $explode[0])) {
              $log_line = $this->userAction($infos[1], implode(' ', $explode));
            } else {
              $log_line = $this->userMessage($infos[1], implode(' ', $explode));
            }
          ;break;   
          case 'NOTICE':
            $this->sendNotice($infos[1]);
          ;break;
        }
        $this->updateLogs($log_line);
      }
    }
  }
      
  private function getTime() {
    return date('[H:i]', time());
  }
  
  private function userAction($user, $action) {
    return $this->getTime().' * '.$user.' '.str_replace('ACTION', '', $action)."\r\n";
  }
  
  private function userMessage($user, $message) {
    return $this->getTime().' <'.$user.'> '.$message."\r\n";
  }
  
  private function pong($ping) {
    fwrite($this->connexion, 'PONG '.$ping);
  }
  
  private function sendNotice($nick) {
    fwrite($this->connexion, 'NOTICE '.$nick.' Pas de notice pour les bots...'."\r\n");
  }
  
  private function updateLogs($log_line) {
    if(mt_rand(0, 10) > 7) {
      if($this->getNumberLogLine() >= $this->max_log_line) {
        unlink($this->max_log_line);
        $this->openLogFile();
      }
    }
    fwrite($this->flog_file, $log_line);
  }
}

$irc = new Irc_log($serveur='deblan.fr', $port=6667, $salon='#general');

$irc->log_file_dir  = '/var/www/web/public/irc.deblan.fr/public_html/';
$irc->log_file_name = 'log_irc.txt';
$irc->max_log_line  = 1000;

$irc->nick  = 'DebStats';
$irc->host  = 'localhost';
$irc->mail  = 'simon@deblan.fr';

$irc->connexion();
?>

Conclusion

Évidemment, il est largement améliorable ^^

Critiques constructives demandées (positives ou pas hein :p) ^^
 

Historique

02 juillet 2008 12:15:52 :
- Changement de constructeur - Déclaration des méthodes __set et __get - modification de la méthode ping
02 juillet 2008 12:26:43 :
- Mise ne page
02 juillet 2008 13:26:33 :
- Ajout de la méthode sendNotice
02 juillet 2008 13:28:29 :
None

Commentaires et avis

signaler à un administrateur
Commentaire de codefalse le 02/07/2008 10:22:49 administrateur CS

J'aime bien le principe perso, c'est un truc tout simple mais qui est bien pensé :)

Sinon au niveau des remarques, je trouve bizar que ton constructeur propose des variables à modifier tel que server ou port, et pas d'autres, tel que nick, host, mail. C'est incohérent. Par ailleur, en php5 la syntaxe conseillée pour le constructeur est __construct. On garde généralement le nom de la classe en tant que fonction pour les compatibilité descendantes avec les anciennes versions de php mais dans ton cas, l'usage des propriétés public/privée/protegée ne rendront pas ton code compatible avec php4 donc ...

Pour ce qui est des setters et des getters, je te conseille aussi d'utiliser les méthodes magiques __set et __get, et de mettre toutes tes variables "propriétés" dans un tableau, comme ca dans tes setters/getters, tu n'a qu'à tester si l'entrée du tableau existe et agir en conséquence, c'est plus simple.

Parce qu'en fait là tu ne peux modifier que les trois entrées que tu n'a pas pu mettre dans le constructeur. Du coup avec l'idée des méthodes magiques, tu peux tout modifier ou non.

Du coup dans ton constructeur tu ne met que l'essentiel, du genre le serveur, le port, l'host, et éventuellement le nom et l'email du bot. Le reste tu attribue des valeurs prédéfinies.

L'utilisateur pourra modifier ce qu'il veux ensuite grace aux méthodes magiques.

Ensuite j'ai pas regardé attentivement toutes tes méthodes, mais la méthode pong m'interpelle. Tu teste dans analyseLine si la requete est "PING", si oui tu appele la méthode pong qui RE-teste si la requete est PING. Pourquoi le faire deux fois ? tu fait tous tes tests dans analyseLine et dans la méthode pong, tu ne fait que fwrite($this->connexion, 'PONG '.$line[1]);

Ma derniere remarque portera sur quelque chose de plus inutile mais à envisager si tu a le temps et la motivation. C'est au niveau conception POO. Tu définit un instance de Irc_Log, et dans cette instance, tu gère les informations concernant le bot (nom, mail, etc).
Normallement, tu devrait faire une classe IrcBot ou tu indique les informations concernant le bot, que tu passe à une classe Irc (par exemple, qui se chargera de la connection) et tu instancie IrcLog (avec les informations qu'il faut) que tu passera aussi à la classe Irc.
Tu sépare ainsi la gestion de la communication sur le serveur, de ton utilisateur (ici le bot) et d'un service d'enregistrement d'évenement (ici le log). Bon apres ca c'est l'extra bonus ! :)

Courage pour la suite ! :)

signaler à un administrateur
Commentaire de Morphinof le 02/07/2008 10:35:48

C'est simple et efficace, je rajouterai rien CodeFalse à déjà relevé tout ce à quoi j'ai pensé. Ah non ! Il à oublié une petite chose ! :D
try { ... }catch (Exception $e) {
die(...);
}
Comment sa die?? ^^ Tu devrais faire ta propre gestion des exception et enlever ces horribles die ;)
Bonne continuation !

signaler à un administrateur
Commentaire de simonviei le 02/07/2008 11:44:35

J'ai longtemps codé en php4 et j'essaye de tout passer mes script en php5 et comme je suis autodidacte...enfin bref commençons :p :

codefalse :
- Pour le constructeur, je suis débile car en plus je le fais sur d'autres scripts, donc je vais vite corriger ça *se tape sur la main*
- En ce qui concerne les setters/getters, je vais vite me documenter après ce message pour mettre ça en place !
- Pour ping c'est en effet un peu débile...je corrige ça vite aussi :p
- Pour la dernière remarque, je vais voir ce que je peux faire :) Je ne promet rien ^^

Morphinof
- Pourquoi mais j'ai encore des flous dans ma tête concernant les exceptions, j'attends de comprendre à peu plus le sujet pour éventuellement faire ma propre gestion des exceptions :p

/me part coder

Je met à jour le code dès que j'ai convenablement avancé.

signaler à un administrateur
Commentaire de codefalse le 02/07/2008 12:06:51 administrateur CS

De là à dire que tu es "débile", quand même ! :p J'en serai presque à supprimer ton post pour non respect de ... toi même ;)

Si tu passe tes scripts de php4 à 5, c'est forcément sur que tu oublie des choses, tu peux pas penser à tout ! Tes erreurs sont justifiées et ton acte est louable (enfin un qui comprends le fait de ne plus utiliser php4 !).

Tu verra, __get et __set, c'est que du bonheur !

Mes remarques ne sont pas très lourdes, ton code est corrigeable en une heure (sauf la dernière partie).

Bonne recherches :) n'hésite pas si tu bloque

signaler à un administrateur
Commentaire de Morphinof le 02/07/2008 12:16:33

En fait c'est pas très compliqué, comme tu as pu le voir le bloc try{ ... }catch(Exception $e){ ... } est fait pour "attraper" les exceptions qui seraient "jetées" par ton application.
Tu dois identifier les erreurs qui peuvent survenir, pennons l'exemple de ta fonction connexion, une exception évidente serait : on n'as pas réussi à ouvrir notre socket parce que par exemple le serveur n'existe pas ou encore le port est bloqué, il te faudra donc tester le $errno de fsockopen et selon sa valeur tu va jeter une exception correspondant au type d'erreur et tu peu même incorporer dans le message de ton exception $errstr, exemple :

throw new UnknowServerException('Exception : '.$errstr);
throw new PortException('Exception : '.$errstr);
(Ce ne sont que deux rapides exemples)

Bien évidement tu vas devoir créer les classes correspondant aux exceptions en les faisant hériter de la classe Exception et ensuite dès que tu va faire appel à ta fonction connexion c'est la que tu met ton bloc try{}catch(){} :)

Pour une meilleure explication : http://classes.scriptsphp.org/article.PHP-5-et-les-exceptions

signaler à un administrateur
Commentaire de malalam le 02/07/2008 22:32:03 administrateur CS 7/10

Hello,

je ne vais pas redire ce qui a été dit; donc, j'ajouterais juste que je trouve ça pas mal comme code : c'est propre, clair, pas mal codé...pour un  débutant en PHP5, c'est très bien :-)

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

Projet de bot irc [ par emilrom ] Bonjour, Je cherche un bon codeur en tcl, C, php, python dans le but de cr&#233;e un bot irc qui doit, par l'interm&#233;diaire de socket, g&#233;rer pb suppression cookies [ par joebuz ] Bonjour, j'avais une section membre toute b&#234;te avec un formulaire de log sur l'index renvoyant a la page connexion et une fois logg&#233; un bout Je vais péter un plomb : Parse error [ par Tupac59 ] Voila mon probl&#232;me, mon code fait 64 lignes html compris et lorque j'essai de lancer ma page avec easy php j'ai ce message : Parse error: parse Problème de portée de variable URGENT [ par Tupac59 ] Voila le problème: depuis la page précédente je POST ['log2'], dans la page suivante je récupère ce log2 dans la variable $log et cela fonctionne puis irc : recuperation des user sur un chan [ par eragon77 ] bonjour, voila tout est en dans le titre je cherche un script php en socket ou autre qui permet de recuperer les users d'un chan irc qui le marque su Chat en php [ par Ramboul ] Salut,Je cherche un tchat en php pour mon site car j'ai déja un tchat mais il requiert d'avoir l'applet java.J'aimerai qu'il redeirige vers irc.quaken IRC ou Jabber ? [ par PIEDPIED13 ] Bonjour Bonjour !Si j'ai bien compris :- Pour esperer avoir un chat qui tourne vraiment sur un site, il faut faire un client IRC et réserver un canal. Verification de fichier [ par godofgames ] Bonjour j'ai une question j'ai un site a realiser pour quelqu'un et cette personne veux pouvoir faire les modification elle meme mais elle ne veux rie Erreur: parse error unexpected $end [ par rouliendelavegas ] BonjourParse error: syntax error, unexpected $end in Voila l'erreur que j'ai en executant ma page licence.php , qui inclut le fichier function_licence Tchat IRC en php [ par Ramboul ] Salut a tous!J'aurais voulu savoir si vous conaissiez un script php comme cgi:irc pour se connecter a un réseau irc mais je voudrais comme cgi:irc mai


Nos sponsors

Sondage...

CalendriCode

Octobre 2008
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Téléchargements

Logiciels à télécharger sur le même thème :



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel BAÏSE, Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,281 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.