3 * This file is part of IrBot, irc robot.
4 * Copyright (C) 2007 Bellière Ludovic
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 // Timeout avant une reconnexion
23 public $socketTimeout = 280;
26 static public $instance = FALSE;
30 static $botVersion = '1.0';
37 static $connection_password;
45 private $core_commands;
49 public static function GetInstance() {
50 if (!self
::$instance) {
51 self
::$instance = new bot();
52 self
::$instance->plugins
= new plugins();
53 self
::$instance->irc
= new irc
;
55 return self
::$instance;
58 private function __construct() {
59 // load config and other things echo "oups main\n";die;
60 $this->formater
= text_format
::GetInstance();
61 $this->tick
= new tick();
64 private function load_core_plugin() {
65 // core plugin is an exeption in do_command
66 $this->plugins
->add_command('core','shownick',0,'Show the current nick used (debug)','mixed');
67 $this->plugins
->add_command('core','nick',1,'Change the current nick','mixed');
68 $this->plugins
->add_command('core','quit',0,'Disconnect and stop the process','mixed');
69 $this->plugins
->add_command('core','restart',0,'Disconnect and restart the process','mixed');
70 $this->plugins
->add_command('core','help',0,'Hmm, je dois recoder cette fonction','mixed');
73 public function launch() {
74 self
::load_core_plugin();
76 $this->C
= @fsockopen
(self
::$server, self
::$port, $errno, $errstr, 10);
78 throw new Exception('Impossible de se connecter au server IRC !',0);
81 if (self
::$connection_password !== false) {
82 $this->put('PASS '.self
::$connection_password);
84 // TODO : be sure for the validity of the connection password (what chain server return if fail ?)
86 $this->put('USER '.self
::$myBotName.' '.self
::$myBotName.'@'.self
::$ip.' '.self
::$domain.' :XBOT');
87 $this->put('NICK '.self
::$myBotName);
90 $this->msg
= $this->get();
91 $this->irc
->parse_get($this->msg
);
93 $this->msg_info
= $msg_info = $this->irc
->get_msg_info();
95 switch ($msg_info['type']) {
100 if ($msg_info['message'][0] == chr(001)) {
102 // we don't need this character
103 $msg_info['message'] = str_replace(chr(001), "", $msg_info['message']);
104 if (strstr($msg_info['message'],' ')===true) {
105 list($cmd,$query) = explode(" ",$msg_info['message']);
107 $cmd = $msg_info['message'];
110 // we don't need this character
111 //$cmd = str_replace(chr(001), "", $msg_info['message']);
115 self
::notice($msg_info['from'],$this->formater
->ctcp('PING VERSION TIME USERINFO CLIENTINFO'));
119 self
::notice($msg_info['from'],$this->formater
->ctcp('RPGBot version '.bot
::$botVersion.' - PHP '.phpversion().' -- par Tornald et Bloodshed'));
123 self
::notice($msg_info['from'],$this->formater
->ctcp('RPGBot'));
127 self
::notice($msg_info['from'],$this->formater
->ctcp(date('Y-m-d H:i:s')));
131 self
::notice($msg_info['from'],$this->formater
->ctcp("PING ".$query));
134 self
::notice($msg_info['from'],$this->formater
->ctcp("UNKNOWN CTCP REQUEST : $cmd"));
138 if ($msg_info['to'] == bot
::$myBotName) {
140 if (preg_match('`^connect ([^ ]+) ([^ ]+)`',$msg_info['message'],$m)) {
141 if ($m[1] == 'admin' && $m[2] == 'mypass') {
143 self
::notice($msg_info['from'],'Vous êtes bien authentifié comme administrateur.');
145 self
::notice($msg_info['from'],'Erreur dans votre login et / ou mot de passe.');
151 if ($msg_info['message'][0] == '!') {
152 $message = substr($msg_info['message'],1);
153 $query = explode(' ',$message);
154 $query_count = count($query);
156 if (isset($this->plugins
->commands
[$query[0]])) {
157 if ($query_count > 1) {
159 if ($this->plugins
->commands
[$query[0]][$query[1]]['type'] == 'mixed' ||
160 ($msg_info['to'] == bot
::$myBotName && $this->plugins
->commands
[$query[0]][$query[1]]['type'] == 'private') ||
161 ($msg_info['to'] == bot
::$channel && $this->plugins
->commands
[$query[0]][$query[1]]['type'] == 'public')) {
163 * $query = array( plugins, method[, arg[, ...]] )
164 * !plugin method[ arg[ ...]]
166 call_user_func_array(array($this->plugins
,'do_command'),array_merge(array('msg_info'=>$msg_info),$query));
169 echo $this->plugins
->commands
[$query[0]][$query[1]]['type']."\n";
170 $this->privmsg($msg_info['from'],"Error with the request.");
173 // no method : need a list of commands
176 $commands = $this->plugins
->list_command($plugin);
177 foreach ($commands as $command_info) {
178 if ($command_info['type'] == 'public') {
179 $get_plugin_method = '!'.$plugin;
181 $get_plugin_method = '/msg ' . bot
::$myBotName . ' !' . $plugin;
184 $this->privmsg($msg_info['from'],$this->formater
->bold('Command :')." $get_plugin_method {$command_info['method']}".(($command_info['accepted_args']>0)?
' [some args...]':''));
186 $help = explode("\n",$command_info['help']);
187 foreach($help as $help_msg) {
188 $this->privmsg($msg_info['from'],$help_msg);
193 var_dump($this->plugins
->commands
);
196 echo 'debug: '.$msg_info['message'][0]."\n";
204 $this->tick
->doAllTicks();
207 } catch (myRuntimeException
$e) {
208 $x = $e->getMessage();
210 $x.= backtrace($e->getTrace());
211 file_put_contents('errorlog',$x);
212 //if ($e->_level < 2 || ($e->_level >= 256 && $e->_level < 1024)) {
213 echo 'Error level : '.$e->_level
."\n\n";
214 throw new Exception('Error occured',0);
216 echo 'Error level : '.$e->_level."\n\n\n\n";
217 throw new Exception("Error occured. Please see errorlog for details.",1);
219 } catch (Exception
$e) {
224 public function joinChannel($channel) {
225 $this->put('JOIN '.$channel);
226 echo "Join channel $channel ...\n";
229 private function nick_change() {
230 echo "New nick : ".self
::$myBotName."\n";
231 $this->put('NICK :'.self
::$myBotName);
234 public function newNick($new=false) {
236 case self
::$myBotName:
237 echo "New nick : [ERR] no changes :". self
::$myBotName . ' == ' . $new ."\n";
240 self
::$myBotName .= '_';
244 self
::$myBotName = $new;
251 * Envoie une notice a un salon / utilisateur
254 * @param string $message
256 public function notice ($to,$message) {
257 self
::put('NOTICE '.$to.' :'.$message."\n");
261 * Envoie un message (PRIVMSG) a un salon / utilisateur
264 * @param string $message
266 public function privmsg ($to,$message) {
267 self
::put('PRIVMSG '.$to.' :'.$message."\n");
270 public function put($command) {
271 if (!is_resource($this->C
)) {
272 throw new Exception('Connection lost...',1);
274 echo debug() ?
'[->' . $command . "\n" : '';
275 fputs($this->C
, $command . "\n");
279 public function get() {
281 stream_set_timeout($this->C
, $this->socketTimeout
);
284 $content = fgets($this->C
, 1024);
286 echo debug() ?
"<-]$content" : '';
288 if ($content != '') {
293 if (time()-$tmp1 >= $this->socketTimeout
) {
294 throw new Exception('TIMEOUT',0);
298 public function shownick() {
299 $this->privmsg(bot
::$channel,bot
::$myBotName."\n");
302 public function nick($newNick) {
303 $this->newNick($newNick);
306 public function help() {
307 $this->privmsg($this->msg_info
['from'],"List of plugins :");
308 foreach($this->plugins
->plugin_list
as $pluginName => $object) {
309 $this->privmsg($this->msg_info
['from'],"!$pluginName");
314 public function restart() {
316 echo 'Restart...'."\n";
319 throw new Exception('Restart...',1);
321 $this->privmsg($this->msg_info
['from'],"Vous n'êtes pas authentifié.");
325 public function quit() {
328 throw new Exception('Quit from',3);
330 $this->privmsg($this->msg_info
['from'],"Vous n'êtes pas authentifié.");
334 public function disconnect($msg='EOL ;') {
335 $this->plugins
->unload_plugin('_all');
336 echo "Closing Link...";
337 if (is_resource($this->C
)) {
338 $this->put('QUIT :'.$msg);
340 echo "\t\t\tdone.\n";
342 echo "\t\t\tError.\nConnection already breack down. ".'bot::disconnect'."\n";
347 private function load_user($file='users.db') {
348 echo "Loading users ...";
349 $ulist = explode("\n",file_get_contents($file));
350 foreach ($ulist as $user) {
351 list($uname,$upass,$uright) = explode(':',$user);
352 $this->users_list
[$uname] = array($upass,$uright);
354 echo "\t\t\tdone.\n";
357 function __destruct() {
358 if (is_resource($this->C
)) {
359 $this->put('QUIT :Error occured');