Staviame IRC bota v PHP

Zdroj: SOOM.cz [ISSN 1804-7270]
Autor: timbulko
Datum: 11.1.2006
Hodnocení/Hlasovalo: 0/0

Určite každý z vás už počul slovo bot alebo IRC bot a povedal si, že by bolo dobré mať takého bota. Tu je návod ako ho vytvoriť.

V prvom rade by bolo vhodné povedať, čo to vlastne IRC bot je. IRC bot je umelý človek, ktorý je na kanále/och 24 hodín denne. Môže vykonávať rôzne funkcie a môže dokonca obsahovať aj jednoduché hry. V tomto článku viac nenapíšem, ale rovno sem dám kód jednoduchého bota zo základnymi funkciami (myslím, že z komentárov, ktoré som priložil sa dá pochopiť ako to celé funguje). Takže tu je:

<?
  $CONFIG = array(
    "server"     => "irc.2600.net",   // Server, na ktorý sa budeme pripájať
    "nick"       => "LamaBot",        // Nick
    "port"       => 6667,             // Port servera
    "channel"    => "#soom,#lamabot", // Kanál/e, na ktoré sa budeme pripájať
    "name"       => "LamaBot",        // Názov bota (potrebné, pre odoslanie príkazu USER)
    "uptime"     => time(),           // Čas spustenia bota
    "db_server"  => "localhost",      // SQL server
    "db_user"    => "root",           // SQL používateľ
    "db_pass"    => "",               // SQL heslo
    "db_name"    => "LamaBot"        // SQL databáza
  );

  /* Pripojíme sa k SQL serveru */
  mysql_connect($CONFIG['db_server'],$CONFIG['db_user'],$CONFIG['db_pass']) or die(mysql_error());
  mysql_select_db($CONFIG['db_name']) or die(mysql_error());

  set_time_limit(0);     // Ignorujeme časový limit
  ignore_user_abort(1);  // Ignorujeme vypnutie užívatelovho browsera (ak užívateľ vypne browser, skript bude bežať ďalej)

  $socket=fsockopen($CONFIG['server'], $CONFIG['port']);  // Najdôležitejši časť bota! Pripojenie k IRC serveru
  if ($socket) {  // Ak sa podarilo pripojiť k IRC serveru
    prikaz("USER ".$CONFIG['nick']." Bot by timbulko :". $CONFIG['name']);  // Identifikujeme sa na serveri
    prikaz("NICK ".$CONFIG['nick'].rand(0,1000));  // Pošleme nick v tvare: nick + náhodné číslo od 0 do 1000 (to je ochrana pred tým, keby bol už nick použitý)
    $e=explode(",",$CONFIG['channel']);  // Ak je zadaných viac ako jeden kanál, tak ich rozdelíme na časti
    foreach ($e as $value) {
      prikaz("JOIN ".$value);  // Pripojíme sa na kanál/e
    }
    prikaz("NICK ".$CONFIG['nick']);  // Zmeníme si nick na normálnu podobu (bez čísla na konci)
    while (!feof($socket)) {          // Opakuj, pokiaľ sa dá čítať zo socketu
      $r=trim(FRead($socket, 512));   // Prečítame 512 znakov zo socketu
      $riadok = ereg_replace(":([^!]*)!([^@]*)@([^ ]*) ([^ ]*) ([^:]*):(.*)","\\1¶\\2¶\\3¶\\4¶\\5¶\\6",$r);  // Rozdelíme riadok socketu na jednotlivé časti
      funkcie($riadok);   // Nasmerujeme na funkciu funkcie
      flush();            // Vyprázdnime zásobník
    }
  }







  function funkcie ($riadok) {  // Definujeme funkciu funkcie
    global $CONFIG,$socket,$r;  // Definujeme si globálne premennú pre túto funkciu
    list($nick,$id,$dns,$prikaz,$kanal,$text) = explode("¶",$riadok);  // Rozdelíme si rozsekaný riadok na jednotlivé premenné


    if (eregi("PING :(.*)",$r)) {  // Ak zacítí bot ping, odpovie na neho pongom
      $e=explode("\n",$r);
      for($i=0;$i<=count($e);$i++) {
        if (eregi("^PING :(.*)$",$e[$i])) {
          $e=explode(":",$e[$i]);
          prikaz("PONG :".$e[1]);
        }
      }
    }

    if ($prikaz=="KICK") {      // Ak bot zachití príkaz kickc, pokúsi sa pripojiť späť
      prikaz("JOIN ".$kanal);
    }

    #################################
    # Od tejto časti sa začína      #
    # funkčná/výkonná časť bota.    #
    # Tu môžete písať svoje vlastné #
    # funkcie. Pre príklad som ich  #
    # sem zopár pridal :)           #
    #################################

     /*  Jednoduchý tvar funkcie:
     
     if (eregi("^funkcia",$text)) {
       príkazy funkcie
     }
     elseif (eregi("^iná funkcia",$text)) {
       príkazy inej funkcie
     }
     
     */



    // užívateľské funkcie
    if (eregi("^!up",$text)) {
      $bezi   = (time()-$CONFIG['uptime']);
      $dni    = floor($bezi/86400);
      $bezi  -= ($dni*86400);
      $hodin  = floor($bezi/3600);
      $bezi  -= ($hodin*3600);
      $minut  = floor($bezi/60);
      $bezi  -= ($minut*60);
      $sekund =  $bezi;
      prikaz("PRIVMSG ".$kanal." :Bot je spusteny ".$dni." dni, ".$hodin." hodin, ".$minut." minut a ".$sekund." sekund");
    }



    elseif(eregi("^!cas",$text)) {
      prikaz("PRIVMSG ".$kanal." :[cas] ".date("H:i:s"));
    }





    // admin funkcie
    elseif (eregi("^#login",$text) && !isset($logins[$nick])) {
      if ($text=="#login") {
        $res=mysql_query("SELECT * FROM `uzivatelia` WHERE `dns` = '".$dns."'");
      }
      else {
        list(,$login,$heslo)=explode(" ",$text);
        $res=mysql_query("SELECT * FROM `uzivatelia` WHERE `login` = '".$login."' AND `pass` = '".$heslo."'");
      }
      if (mysql_num_rows($res)==1) {
        $row=mysql_fetch_array($res);
        $logins[$nick]['prava']      = $row['prava'];
        $logins[$nick]['last_login'] = $row['last_login'];
        $logins[$nick]['login']      = $row['login'];
        $logins[$nick]['pass']       = $row['pass'];
        $logins[$nick]['id']         = $row['id'];
        $logins[$nick]['dns']        = $row['dns'];
        $dl=date("j.n.Y o H:i:s",$logins[$nick]['last_login']);
        mysql_query("
          UPDATE `uzivatelia` SET
          `last_login` = '".time()."',
          `dns` = '".$dns."'
          WHERE `id` = '".$row['id']."';
        ");
        prikaz("NOTICE ".$nick." :Uzivatel ".$nick." bol uspesne prihlaseny! Naposledy ste boli prihlaseny dna ".$dl);
      }
      else {
        prikaz("NOTICE ".$nick." :Uzivatela ".$nick." sa nepodarilo prihlasit!");
      }
    }



    elseif (eregi("^#op",$text)) {
      if ($logins[$nick]['prava']>=1) {
        if ($text=="#op") {
          prikaz("MODE ".$kanal." +o ".$nick);
        }
        else {
          $e=explode(" ",$text);
          prikaz("MODE ".$kanal." +o ".$e[1]);
        }
      }
      else {
        prikaz("NOTICE ".$nick." :Nie ste prihlaseny!");
      }
    }



    elseif (eregi("^#deop",$text)) {
      if ($logins[$nick]['prava']>=1) {
        if ($text=="#deop") {
          prikaz("MODE ".$kanal." -o ".$nick);
        }
        else {
          $e=explode(" ",$text);
          prikaz("MODE ".$kanal." -o ".$e[1]);
        }
      }
      else {
        prikaz("NOTICE ".$nick." :Nie ste prihlaseny!");
      }
    }



    elseif (eregi("^#kick",$text)) {
      if ($logins[$nick]['prava']>=1) {
        $e=explode(" ",$text,3);
        prikaz("KICK ".$kanal." ".$e[1]." :".$e[2]);
      }
      else {
        prikaz("NOTICE ".$nick." :Nie ste prihlaseny!");
      }
    }





    // SuperAdmin funkcie
    elseif (eregi("^~quit",$text)) {
      if ($logins[$nick]['prava']==2) {
        prikaz("PRIVMSG ".$kanal." :Odchadzam...");
        exit;
      }
      else {
        prikaz("PRIVMSG ".$kanal." :Uzivatel ".$nick." nie je prihlaseny alebo nie je administratorom!");
      }
    }



    elseif (eregi("^~join",$text)) {
      if ($logins[$nick]['prava']==2) {
        $e=explode(" ",$text);
          prikaz("PRIVMSG ".$kanal." :Pripajam sa na kanal ".$e[1]."...");
          if (file_exists("kluc.dat")) {
            $open=FOpen("kluc.dat","r");
            $read=FRead($open,filesize("kluc.dat"));
            FClose($open);
            prikaz("JOIN ".$e[1]." ".$read);
          }
          else {
            prikaz("JOIN ".$e[1]);
          }
          prikaz("PRIVMSG ".$kanal." :Bol som pripojeny na kanal ".$e[1]."!");
      }
      else {
        prikaz("PRIVMSG ".$kanal." :Uzivatel ".$nick." nie je prihláseny alebo nie je administratorom!");
      }
    }



    elseif (eregi("^~part",$text)) {
      if ($logins[$nick]['prava']==2) {
        if ($text=="~part") {
          prikaz("PRIVMSG ".$kanal." :Odchadzam...");
          prikaz("PART ".$kanal);
        }
        else {
          $e=explode(" ",$text);
          prikaz("PRIVMSG ".$kanal." :Odpajam sa z kanalu ".$e[1]."...");
          if ($kanal!=$e[1]) {
            prikaz("PRIVMSG ".$e[1]." :Odchadzam...");
          }
          prikaz("PART ".$e[1]);
          prikaz("PRIVMSG ".$kanal." :Bol som odpojeny z kanalu ".$e[1]."!");
        }
      }
      else {
        prikaz("PRIVMSG ".$kanal." :Uzivatel ".$nick." nie je prihlaseny alebo nie je administratorom!");
      }
    }
  }



  // a este fce prikaz, ktora odosle socket
  function prikaz($prikaz) {
    global $socket,$CONFIG,$bites;
    FWrite($socket, $prikaz."\n\r");
  }
?>


A ešte tabuľka pre funkciu #login:

CREATE TABLE `uzivatelia` (
`id` INT NOT NULL AUTO_INCREMENT,
`login` VARCHAR(50) NOT NULL DEFAULT '',
`pass` VARCHAR(50) NOT NULL DEFAULT '',
`last_login` INT DEFAULT '0',
`prava` INT NOT NULL DEFAULT '1',
PRIMARY KEY (`id`)
);


Kompletného bota si môžete stiahnuť na adrese http://euphoria.wz.cz/lamabot.zip



.::timbulko::.