Jacek Kowalski
2012-06-25 41c5d21ff614abede5252fd31ec61259e3589f6c
commit | author | age
8bd4d9 1 <?php
JK 2 /**
3  * Klasa obsługująca żądania wysyłane do bota
4  */
5 class BotPull {
6     private $PDO;
7     
8     private function init() {
9         if(is_file(BOT_TOPDIR.'/cache/functions.sqlite')) {
10             $this->PDO = new PDO('sqlite:'.BOT_TOPDIR.'/cache/functions.sqlite');
11             $this->PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
12             $this->PDO->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_TO_STRING);
13             return;
14         }
15         
16         $functions = array();
17         
18         $modules = glob(BOT_TOPDIR.'/modules/*', GLOB_ONLYDIR);
19         foreach($modules as $dir) {
20             if(!is_file($dir.'/init.php')) {
21                 continue;
22             }
23             
24             $class = include_once($dir.'/init.php');
25             if(!$class || !class_exists($class, FALSE)) {
26                 continue;
27             }
28             
29             $init = new $class;
30             if(!($init instanceof BotModuleInit)) {
31                 continue;
32             }
33             
34             $row = $init->register();
35             if(!is_array($row)) {
36                 $row = array();
37             }
38             
39             foreach($row as $name => &$value) {
40                 if(!is_array($value)) {
41                     unset($row[$name]);
42                     continue;
43                 }
44                 
45                 foreach($value as &$val) {
46                     $val['dir'] = '/modules/'.basename($dir).'/';
47                     $val['init'] = $class;
48                     $val['file'] = $val['file'];
49                 }
50                 
51                 $name2 = funcs::utfToAscii(strtolower($name));
52                 if($name != $name2) {
53                     if(isset($row[$name2])) {
54                         $row[$name2] = array_merge_recursive($row[$name2], $row[$name]);
55                     }
56                     else
57                     {
58                         $row[$name2] = $row[$name];
59                     }
60                     
61                     unset($row[$name]);
62                 }
63             }
64             
65             $functions = array_merge_recursive($functions, $row);
66         }
67         
68         try {
69             $this->PDO = new PDO('sqlite:'.BOT_TOPDIR.'/cache/functions.sqlite');
70             $this->PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
71             $this->PDO->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_TO_STRING);
72             
73             $this->PDO->query('CREATE TABLE functions (
74                 name VARCHAR(50),
75                 priority INT,
76                 dir VARCHAR(255),
77                 init VARCHAR(255),
78                 file VARCHAR(255),
79                 class VARCHAR(255),
80                 method VARCHAR(255),
81                 params TEXT,
82                 PRIMARY KEY (
83                     name ASC,
84                     priority ASC
85                 )
86             )');
87             
88             $this->PDO->query('CREATE INDEX file ON functions (dir, file)');
89             
90             $st = $this->PDO->prepare('INSERT INTO functions (name, priority, dir, init, file, class, method, params) VALUES (?, ?, ?, ?, ?, ?, ?, ?)');
91             
92             $this->PDO->beginTransaction();
93             foreach($functions as $name => $funcs) {
94                 $name = funcs::utfToAscii(strtolower($name));
95                 foreach($funcs as $priority => $func) {
96                     if(!isset($func['params'])) {
97                         $func['params'] = NULL;
98                     }
99                     
100                     $st->execute(array($name, $priority, $func['dir'], $func['init'], $func['file'], $func['class'], $func['method'], serialize($func['params'])));
101                 }
102             }
103             $this->PDO->commit();
104         }
105         catch(Exception $e) {
106             @unlink(BOT_TOPDIR.'/cache/functions.sqlite');
107             throw $e;
108         }
109     }
110     
111     /**
112      * Przetwarza wiadomość do bota
113      * @param BotMessage $msg Wiadomość
114      */
115     function __construct(BotMessage $msg) {
116         try {
117             $this->init();
118             
119             $st = $this->PDO->prepare('SELECT dir, file, class, method, params FROM functions WHERE name=? ORDER BY priority ASC');
120             $st->execute(array($msg->command));
121             $data1 = $st->fetchAll();
122             $st->execute(array('*'));
123             $data2 = $st->fetchAll();
124             
125             $data = array_merge($data1, $data2);
126             unset($data1, $data2);
127             
128             $return = NULL;
129             
130             foreach($data as $func) {
131                 if(!is_file(BOT_TOPDIR.$func['dir'].$func['file'])) {
132                     $st = $this->PDO->prepare('DELETE FROM functions WHERE dir=? AND file=?');
133                     $st->excecute(array($func['dir'], $func['file']));
134                     continue;
135                 }
136                 
137                 require_once(BOT_TOPDIR.$func['dir'].$func['file']);
138                 
139                 $class = new $func['class'];
140                 $return = $class->$func['method']($msg, unserialize($func['params']));
141                 
142                 if($return instanceof BotMsg) {
143                     break;
144                 }
145             }
146             
147             if(!($return instanceof BotMsg)) {
148                 $return = new BotMsg('Nieznane polecenie. Wpisz <b>help</b> by uzyskać listę komend.');
149             }
150         }
151         catch(Exception $e) {
152             $return = new BotMsg('Wystąpił błąd podczas przetwarzania poleceń. Komunikat:<br />'.nl2br($e));
153         }
154         
155         try {
156             $class = substr(get_class($msg), strlen('BotMessage'));
157             if(!$class) {
158                 throw new Exception('Wiadomość dostarczona za pomocą nieznanego interfejsu.');
159             }
160             
161             $class = 'BotMsg'.$class;
162             
163             try {
164                 $class = new $class($return);
165             }
166             catch(Exception $e) {
167                 $class = new $class(new BotMsg('Wystąpił błąd podczas przetwarzania poleceń. Komunikat:<br />'.nl2br($e)));
168             }
169             
170             $class->sendPullResponse();
171         }
172         catch(Exception $e) {
173             echo 'Wystąpił błąd podczas przetwarzania poleceń. Komunikat: '.$e;
174         }
175     }
176 }
177 ?>