added ScaleBot
[PHP-P10.git] / Bots / ScaleGod.class.php
1 <?php
2 /******************************* PHP-P10 v2 *****************************
3  *   Copyright (C) 2011-2012  Philipp Kreil (pk910)                     *
4  * This program is free software: you can redistribute it and/or modify *
5  * it under the terms of the GNU General Public License as published by *
6  * the Free Software Foundation, either version 3 of the License, or    *
7  * (at your option) any later version.                                  *
8  *                                                                      *
9  * This program is distributed in the hope that it will be useful,      *
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
12  * GNU General Public License for more details.                         *
13  *                                                                      *
14  * You should have received a copy of the GNU General Public License    *
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
16  *                                                                      *
17  ************************************************************************
18  *
19  *  Bots/ScalaGod.class.php
20  *
21  * simple Scala debugger...
22  *
23  */
24
25 class {$_NAME} extends Bot {
26         private $uplink;
27         private $bot, $execcache = array();
28
29         public function load($uplink, $old = false) {
30                 $this->uplink = $uplink;
31                 if(!$old) {
32                         $nick = "Scala";
33                         $ident = "Scala";
34                         $host = "services.....";
35                         $ip = "0::0";
36                         $realname = "Scala Scala Scala Scala Scala";
37                         $modes = "ioknISD";
38                         $this->bot = $this->uplink->addUser($nick,$ident,$host,$ip,$modes,$realname);
39                         if(is_a($this->bot, "P10_User")) {
40                                 $this->uplink->join($this->bot, "#dev", P10_Channel::USERPRIV_VOICE);
41                                 $this->uplink->join($this->bot, "#opers", P10_Channel::USERPRIV_OPED);
42                         }
43                                 
44                 } else {
45                         $this->bot = $old;
46                 }
47
48                 ModCMD::bind($this, BIND_CHANMSG, "recive_privmsg");
49                 ModCMD::bind($this, BIND_QUIT, "recive_quit");
50         }
51
52         public function unload($rehash = false) {
53                 foreach($this->execcache as $id => $entry) {
54                         fclose($entry['pipes'][1]);
55                         fclose($entry['pipes'][2]);
56                         proc_terminate($entry['proc'],9);
57                 }
58                 $this->execcache = array();
59                 if($rehash) {
60                         return $this->bot;
61                 } else {
62                         $this->uplink->delUser($this->bot, "Bye.");
63                 }
64         }
65
66         public function loop() {
67                 foreach($this->execcache as $id => $entry) {
68                         if(!$this->checkstate($entry)) {
69                                 unlink("tmp/Debug_".$entry['id'].".scala");
70                                 unset($this->execcache[$id]);
71                         }
72                 }
73         }
74
75         function recive_privmsg($user, $channel, $message) {
76                 $opOnScalaChannel = false;
77                 $ScalaChannel = P10_Channel::getChannelByName("#dev");
78                 if($ScalaChannel) {
79                         $privs = $ScalaChannel->getUserPrivs($user);
80                         $opOnScalaChannel = ($privs & P10_Channel::USERPRIV_OPED);
81                 }
82                 if(!$user->getModes()->hasMode('o') && !$opOnScalaChannel) return 0;
83                 $exp=explode(" ", $message, 2);
84                 switch (strtolower($exp[0])) {
85                         case "~scala":
86                                 if(count($this->execcache) > 5) {
87                                         $this->uplink->notice($this->bot, $user, "too many running scala processes at the moment!");
88                                         return;
89                                 }
90                                 $entry=array();
91                                 $entry['channel'] = $channel;
92                                 $entry['id'] = rand(1, 999999);
93                                 if(preg_match("#pastebin\.com/([a-zA-Z0-9]*)$#i", $exp[1])) {
94                                         $pasteid = explode("/", $exp[1]);
95                                         $pasteid = $pasteid[count($pasteid)-1];
96                                         $scalacontent = file_get_contents("http://pastebin.com/download.php?i=".$pasteid);
97                                         if(preg_match("#Unknown Paste ID!#i", $scalacontent)) {
98                                                 $this->uplink->notice($this->bot, $user, "Unknown Paste ID!");
99                                                 return;
100                                         }
101                                         $scalacode = "import scala._
102                             ".$scalacontent."
103                     ";
104                                 } else {
105                                         $scalacode = "import scala._
106                             ".$exp[1]."
107                     ";
108                                 };
109                                 $fp = fopen("tmp/Debug_".$entry['id'].".scala", "w");
110                                 fwrite($fp, $scalacode);
111                                 fclose($fp);
112                                 $descriptor = array(0 => array("pipe", "r"),1 => array("pipe", "w"),2 => array("pipe", "w"));
113                                 $entry['proc'] = proc_open('scala tmp/Debug_'.$entry['id'].'.scala', $descriptor, $entry['pipes']);
114                                 if(!is_resource($entry['proc'])) {
115                                         $this->uplink->notice($this->bot, $user, "error while loading c!");
116                                         return;
117                                 }
118                                 $entry['time'] = time();
119                                 fclose($entry['pipes'][0]);
120                                 $this->execcache[] = $entry;
121                                 break;
122                 }
123         }
124
125         function recive_quit($user, $reason) {
126                 if($user === $this->bot) {
127                         $this->load($this->uplink);
128                 }
129         }
130
131         function checkstate($entry) {
132                 $data = proc_get_status($entry['proc']);
133                 if(!$data['running']) {
134                         $out="";
135                         while(!feof($entry['pipes'][1])) {
136                                 $out .= fgets($entry['pipes'][1], 128);
137                         }
138                         $eout="";
139                         while(!feof($entry['pipes'][2])) {
140                                 $eout .= fgets($entry['pipes'][2], 128);
141                         }
142                         if($out != "") {
143                                 $out=str_replace("\r","",$out);
144                                 $lines=explode("\n",$out);
145                                 $i=0;
146                                 foreach($lines as $line) {
147                                         if($line == "") continue;
148                                         $i++;
149                                         if($i>1000) {
150                                                 $this->uplink->privmsg($this->bot, $entry['channel'], "too many lines!");
151                                                 break;
152                                         }
153                                         $this->uplink->privmsg($this->bot, $entry['channel'], $line);
154                                 }
155                         }
156                         if($eout != "") {
157                                 $eout=str_replace("\r","",$eout);
158                                 $lines=explode("\n",$eout);
159                                 $i=0;
160                                 foreach($lines as $line) {
161                                         if($line == "") continue;
162                                         $i++;
163                                         if($i>1000) {
164                                                 $this->uplink->privmsg($this->bot, $entry['channel'], "too many lines!");
165                                                 break;
166                                         }
167                                         $this->uplink->privmsg($this->bot, $entry['channel'], "\ 34".$line."\ 3");
168                                 }
169                         }
170                         fclose($entry['pipes'][1]);
171                         fclose($entry['pipes'][2]);
172                         proc_close($entry['proc']);
173                         return false;
174                 } else {
175                         if($entry['time']+10 > time()) {
176                                 return true;
177                         } else {
178                                 //TIMEOUT
179                                 if($entry['term']) {
180                                         fclose($entry['pipes'][1]);
181                                         fclose($entry['pipes'][2]);
182                                         proc_terminate($entry['proc'],9);
183                                         $this->uplink->privmsg($this->bot, $entry['channel'], "Scala hard timeout. sending SIGKILL");
184                                         return false;
185                                 } else {
186                                         proc_terminate($entry['proc']);
187                                         $entry['term']=true;
188                                         $this->uplink->privmsg($this->bot, $entry['channel'], "Scala timeout. (maximum of 10 seconds exceeded)  sending SIGTERM");
189                                         return true;
190                                 }
191                         }
192                 }
193         }
194
195 }
196
197 ?>