Advertisement
Guest User

Untitled

a guest
Jan 29th, 2012
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 14.05 KB | None | 0 0
  1. <?php
  2.    
  3.     set_time_limit(0); //Don't kill the script after a set time.
  4.     header('Content-type: text/plain'); //Easier display of the log. Maybe in the future log will look better.
  5.     error_reporting(E_ALL); //Show any error the pops up.
  6.    
  7.     /* -- Disable output buffering -- */
  8.     ob_implicit_flush(true);
  9.     ob_end_flush();
  10.  
  11.    
  12.     /**
  13.      * Registry
  14.      * This object holds the global variables, it will be passed to every object.
  15.      *
  16.      * @package tests
  17.      * @author Truth
  18.      * @copyright 2011
  19.      * @access public
  20.      */
  21.     class Registry {
  22.         public $vars = array();
  23.  
  24.         /**
  25.          * Registry::__construct()
  26.          *
  27.          * @param mixed $vars   The constructor accepts an array of variables for first use.
  28.          *
  29.          * @return \Registry
  30.          */
  31.         public function __construct($vars) {
  32.             if (is_array($vars)) { $this->vars = $vars; }
  33.         }
  34.        
  35.         /**
  36.          * Registry::__set()
  37.          *
  38.          * @param mixed $index
  39.          * @param mixed $value
  40.          * @return void
  41.          */
  42.         public function __set($index, $value) {
  43.             $this->vars[$index] = $value;
  44.         }
  45.        
  46.         /**
  47.          * Registry::__get()
  48.          *
  49.          * @param mixed $index
  50.          * @return mixed
  51.          */
  52.         public function __get($index) {
  53.             return $this->vars[$index];
  54.         }
  55.     }
  56.    
  57.     class Bot {
  58.        
  59.         /**
  60.          * $registry
  61.          * @var Holds the registry object
  62.          */
  63.         protected $registry;
  64.        
  65.         /**
  66.          * $conn
  67.          * @var resource Holds the connection
  68.          */
  69.         protected $conn;
  70.        
  71.         /**
  72.          * $data
  73.          * @var Holds the data being read right now
  74.          */
  75.         protected $data;
  76.        
  77.         /**
  78.          * $channels
  79.          * @var array   Holds an array of Channel objects which the bot is on
  80.          */
  81.         protected $channels = array();
  82.  
  83.         /**
  84.          * $users
  85.          * @var array   Holds an array of User objects. A list of all known users to the bot
  86.          */
  87.         protected $users = array();
  88.        
  89.         /**
  90.          * $me
  91.          * @var string  Holds the bot's nickname
  92.          */
  93.         private $me;
  94.  
  95.         /**
  96.          * Bot::__construct()
  97.          * Set global variables from registry and connect.
  98.          *
  99.          * @param mixed $registry
  100.          *
  101.          * @return \Bot
  102.          */
  103.         public function __construct($registry) {
  104.             $this->registry = $registry;
  105.             $this->connect();
  106.         }
  107.  
  108.         /**
  109.          * Bot::putUser()
  110.          * Add a user to the global user list found on $this->users.
  111.          *
  112.          * @param string $user  The nickname or full address of the user.
  113.          * @param        $channel
  114.          *
  115.          * @return void
  116.          */
  117.         protected function putUser($user, $channel) {
  118.             if (!empty($this->users[$user])) {
  119.                 return;
  120.             }
  121.             $matches = array();
  122.             #Full address match
  123.            if (preg_match("|^:?([^\s!]+)![^\s@]+@\S+$|i", $user, $matches)) {
  124.                 $this->users[$matches[1]] = new User($matches[1], $user);
  125.                 $channel->nicklist[$matches[1]] = $this->users[$matches[1]];
  126.                 return;
  127.             }
  128.             #Only nickname match
  129.            else if (preg_match("|^([^!@\s]+)$|", $user, $matches)) {
  130.                 $this->users[$matches[1]] = new User($matches[1]);
  131.                 $channel->nicklist[$matches[1]] = $this->users[$matches[1]];
  132.             }
  133.             else throw new Exception("Invalid username or address.");
  134.         }
  135.        
  136.         /**
  137.          * Bot::delUser()
  138.          * Removes a user from the bot.
  139.          *
  140.          * @param string $user  The user to remove.
  141.          * @return void
  142.          */
  143.         protected function delUser($user) {
  144.             if (!empty($this->users[$user])) {
  145.                 $this->users[$user] = null;
  146.             }
  147.         }
  148.         /**
  149.          * Bot::debug()
  150.          * Outputs a debug line.
  151.          *
  152.          * @param mixed $data   The data to output
  153.          * @param mixed $target The target of the output (in, out)
  154.          * @return void
  155.          */
  156.         protected function debug($data, $target) {
  157.             echo date('H:i:s')." ".strtoupper($target).": $data \r\n";
  158.         }
  159.        
  160.         /**
  161.          * Bot::in()
  162.          * Writes a line of $data onto the connection. Note the use of "\r\n" it is important!
  163.          *
  164.          * @param mixed $data  The line to write.
  165.          * @return void
  166.          */
  167.         protected function in($data) {
  168.             fwrite($this->conn, $data."\r\n");
  169.             $this->debug($data, 'in');
  170.         }
  171.         /**
  172.          * Bot::out()
  173.          * Reads out data from the connection.
  174.          *
  175.          * @return void
  176.          */
  177.         protected function out() {
  178.             $this->data = fgets($this->conn);
  179.             $this->data = preg_replace("|[\r\n]|", "", $this->data);
  180.             $this->debug($this->data, 'out');
  181.         }
  182.  
  183.         /**
  184.          * Bot::auth()
  185.          * Used to authenticate a user as an administrator.
  186.          * Will have a database connection and testing in the future.
  187.          *
  188.          * @param string $user
  189.          * @param string $pass
  190.          *
  191.          * @return bool
  192.          */
  193.         protected function auth($user, $pass) {
  194.             if (strtolower($user) == 'truth' && strtolower($pass) == '1499823') {
  195.                 return true;
  196.             }
  197.             return false;
  198.         }
  199.        
  200.         /**
  201.          * Bot::connect()
  202.          * Connects to the IRC server and sends in basic data.
  203.          *
  204.          * @return void
  205.          */
  206.         public function connect() {
  207.             $this->conn = fsockopen($this->registry->server, $this->registry->port, $errno, $errstr);
  208.             if (!$this->conn) { throw new Exception("Connection failed! ($errno) $errstr"); }
  209.             if (!empty($this->registry->pass)) { $this->in("PASS {$this->registry->pass}"); }
  210.             $this->in("USER {$this->registry->mnick} 0 * :{$this->registry->rname}");
  211.             $this->in("NICK {$this->registry->mnick}");
  212.             $this->main();
  213.         }
  214.        
  215.         /**
  216.          * Bot::join()
  217.          * Join a channel
  218.          *
  219.          * @param string $channel
  220.          * @return void
  221.          */
  222.         public function join($channel) {
  223.             if (empty($this->channels[$channel])) {
  224.                 $this->in("JOIN :$channel");
  225.                 $this->channels[$channel] = new Channel($channel);
  226.             }
  227.         }
  228.        
  229.         /**
  230.          * Bot::part()
  231.          * Part a channel
  232.          *
  233.          * @param mixed $channel
  234.          * @return void
  235.          */
  236.         public function part($channel) {
  237.             if (empty($this->channels[$channel])) {
  238.                 $this->in("PART :$channel");
  239.                 $this->channels[$channel] = null;
  240.             }
  241.         }
  242.        
  243.         public function msg($target, $msg) {
  244.             $this->in("PRIVMSG $target :$msg");
  245.         }
  246.        
  247.         public function quit($msg = "Goodbye") {
  248.             $this->in("QUIT :$msg");
  249.         }
  250.  
  251.         /**
  252.          * @param User $user
  253.          *
  254.          * @return boolean Whether the user is an admin or not.
  255.          */private function isAdmin($user) {
  256.             return $user->getAdmin();
  257.         }
  258.  
  259.         /**
  260.          * @param string $fullAddress
  261.          *
  262.          * @return User
  263.          */private function identifyUser($fullAddress) {
  264.             $nick = explode("!", $fullAddress);
  265.             $nick = str_replace(":", "", $nick[0]);
  266.             return $this->users[$nick];
  267.         }
  268.        
  269.         /**
  270.          * Bot::main()
  271.          * The main functions. Runs as long as there's connection.
  272.          *
  273.          * @return void
  274.          */
  275.         public function main() {
  276.             while (!feof($this->conn)) {
  277.                 $this->out();
  278.                 $data = explode(" ", $this->data);
  279.                 #Ping pong
  280.                if ($data[0] == "PING") {
  281.                     @$this->in("PONG $data[1]");
  282.                 }
  283.                 if ($data[1] == "005") {
  284.                     if (empty($this->me)) {
  285.                         $this->me = $data[2];
  286.                     }
  287.                     $variables = array_slice($data, 3);
  288.                     foreach ($variables as $var) {
  289.                         if ($var == ":are") { break; }
  290.                         $array = explode('=', $var);
  291.                         $key = $array[0];
  292.                         $value = empty($array[1]) ? '' : $array[1];
  293.                         $this->registry->$key = $value;
  294.                     }
  295.                 }
  296.                 #End of MOTD or MOTD missing
  297.                if ($data[1] == "367" || $data[1] == "422") {
  298.                     $this->join("#Welcome");
  299.                 }
  300.                 if ($data[1] == "353") {
  301.                     $names = array_slice($data, 5);
  302.                     $channel = $data[4];
  303.                     echo "|[:{$this->registry->STATUSMSG}]|"; //FIGURE OUT WHY NOT REPLACING!!
  304.                     foreach ($names as $name) {
  305.                         $name = preg_replace("|[:{$this->registry->STATUSMSG}]|", '', $name);
  306.                         //echo "str_replace(|[:{$this->registry->STATUSMSG}]|, '', $name);";
  307.                         echo $name.' ';
  308.                         $this->putUser($name, $this->channels[$channel]);
  309.                         //$this->channels[$channel]->putUser($name);
  310.                     }
  311.                 }
  312.                 if ($data[1] == "366") {
  313.                     //var_dump($this->channels, $this->users, $this->registry);
  314.                 }
  315.                 if ($data[1] == "PRIVMSG") {
  316.                    
  317.                     $user = $this->identifyUser($data[0]);
  318.                     $target = $data[2];
  319.                     $msg = str_replace(":", "", array_slice($data, 3));
  320.                     //$str_msg = implode(" ", $msg);
  321.                    
  322.                     if ($target == $this->me) {
  323.                         if ($msg[0] == "@auth") {
  324.                             if (!$this->isAdmin($user)) {
  325.                                 $this->msg($user->nick, "Acknowledged. Please hold.");
  326.                                 $auth = $this->auth($msg[1], $msg[2]);
  327.                                 if ($auth) {
  328.                                     $user->setAdmin(true);
  329.                                     $this->msg($user->nick, "Authentication Succesful!");
  330.                                 }
  331.                                 else {
  332.                                     $this->msg($user->nick, "Authentication Failed. User/Password match is wrong.");
  333.                                 }
  334.                             }
  335.                             else {
  336.                                 $this->msg($user->nick, "You are already identified as an admin. No need to identify twice.");
  337.                             }
  338.                         }
  339.  
  340.                     }
  341.                     if ($this->isAdmin($user)) {
  342.                         if ($msg[0] == "@die") {
  343.                             $this->quit("Requested by Admin - $user->nick");
  344.                         }
  345.                         if ($msg[0] == "@say") {
  346.                             $this->msg($target, implode(" ",array_slice($msg, 1)));
  347.                         }
  348.                     }
  349.                    
  350.                     //$this->in("PRIVMSG #Welcome :{$user->nick} said on $target: $str_msg");
  351.                    
  352.                 }
  353.             }
  354.         }
  355.     }
  356.    
  357.     class Channel {
  358.        
  359.         public $name;
  360.         public $nicklist;
  361.        
  362.         public function __construct($name) {
  363.             if (!preg_match("/^#/", $name)) { //Channels should begin with #, if not add one.
  364.                 $name = "#$name";
  365.             }
  366.             $this->name = $name;
  367.         }
  368.        
  369.         public function __get($nick) {
  370.             return $this->nicklist[$nick];
  371.         }
  372.         public function __set($nick, $newnick) {
  373.             $this->nicklist[$nick] = $newnick;
  374.         }
  375.        
  376.         public function putUser($nick) {
  377.             $this->nicklist[$nick] = new User($nick);
  378.         }
  379.         public function delUser($nick) {
  380.             if (isset($this->nicklist[$nick])) {
  381.                 unset($this->nicklist[$nick]);
  382.             }
  383.         }
  384.        
  385.     }
  386.    
  387.     class User {
  388.         /**
  389.          * $nick
  390.          * @var holds the user's nickname
  391.          */
  392.         public $nick = '';
  393.        
  394.         /**
  395.          * $fullAddress
  396.          * @var holds the user's full address in the form of nick!user@host.
  397.          */
  398.         public $fullAddress = '';
  399.        
  400.         /**
  401.          * $admin
  402.          * @var holds the administration status for the user.
  403.          */
  404.         protected $admin = false;
  405.        
  406.         public function __construct($nick, $fullAddress = '') {
  407.             //var_dump(debug_backtrace());
  408.             if (!empty($this->fullAddress)) $this->$fullAddress = $fullAddress;
  409.             $this->nick = $nick;
  410.         }
  411.        
  412.         public function getAdmin() {
  413.             return $this->admin;
  414.         }
  415.         public function setAdmin($admin) {
  416.             $this->admin = $admin;
  417.         }
  418.        
  419.         public function rename($newNick) {
  420.             $oldNick = $this->nick;
  421.             $this->nick = $newNick;
  422.             $this->fullAddress = str_replace($oldNick, $newNick, $this->fullAddress);
  423.         }
  424.         public function __toString() {
  425.             return $this->nick;
  426.         }
  427.     }
  428.    
  429.     //---------------------------------
  430.     $registry = new Registry(array(
  431.        
  432.         "mnick" => "TruthBot",
  433.         "anick" => "TruthBot2",
  434.         "rname" => "The Bot of Truth",
  435.         "server" => "localhost",
  436.         "port" => 6667,
  437.         "admin" => array("Truth"),
  438.        
  439.     ));
  440.     $bot = new Bot($registry);
  441.  
  442. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement