Jacek Kowalski
2016-02-12 6411a4f462fcd039ce4d233aaf28a5186b20eeea
commit | author | age
8bd4d9 1 <?php
JK 2 class BotAPIGGHTTPException extends Exception {
3     private $httpcode;
4     private $content;
5     
6     function __construct($msg, $httpcode, $content) {
7         $this->httpcode = $httpcode;
8         $this->content = $content;
9dae9f 9         parent::__construct($msg.' Błąd '.$httpcode);
8bd4d9 10     }
JK 11     
12     function __get($name) {
13         return $this->$name;
14     }
15 }
16 class BotAPIGGXMLException extends Exception {
17     private $content;
18     
19     function __construct($msg, $content) {
20         $this->content = $content;
21         parent::__construct($msg);
22     }
23     
24     function __get($name) {
25         return $this->$name;
26     }
27 }
28
29 class BotAPIGGReplyException extends Exception {
30     private $xml;
31     
32     function __construct($msg, SimpleXMLElement $xml) {
33         $this->xml = $xml;
34         parent::__construct($msg);
35     }
36     
37     function __get($name) {
38         return $this->$name;
39     }
40     
41     function __toString() {
42         return $this->getMessage().' Błąd '.((string)$this->xml->status).': '.((string)$this->xml->errorMsg);
43     }
44 }
45
46 class BotAPIGG extends config {
bcbe9c 47     private static $token;
8bd4d9 48     
JK 49     const STATUS_DOSTEPNY = 2;
50     const STATUS_DOSTEPNY_DESC = 4;
51     const STATUS_ONLINE = 2;
52     const STATUS_ONLINE_DESC = 4;
53     
54     const STATUS_ZAJETY = 3;
55     const STATUS_ZAJETY_DESC = 5;
56     const STATUS_AWAY = 3;
57     const STATUS_AWAY_DESC = 5;
58     
59     const STATUS_NIE_PRZESZKADZAC = 33;
60     const STATUS_NIE_PRZESZKADZAC_DESC = 34;
61     const STATUS_DND = 33;
62     const STATUS_DND_DESC = 34;
63     
64     const STATUS_POROZMAWIAJ = 23;
65     const STATUS_POROZMAWIAJ_DESC = 24;
66     const STATUS_CHAT = 23;
67     const STATUS_CHAT_DESC = 24;
68     
69     const STATUS_NIEWIDOCZNY = 20;
70     const STATUS_NIEWIDOCZNY_DESC = 22;
71     const STATUS_INVISIBLE = 20;
72     const STATUS_INVISIBLE_DESC = 22;
73     
fb87e0 74     private function httpQuery($address, $curlopts = array(), $useToken = TRUE, $parseXML = TRUE) {
8bd4d9 75         if(!is_array($curlopts)) {
JK 76             $curlopts = array();
77         }
78         
79         if($useToken) {
80             if(!isset($curlopts[CURLOPT_HTTPHEADER]) || !is_array($curlopts[CURLOPT_HTTPHEADER])) {
81                 $curlopts[CURLOPT_HTTPHEADER] = array();
82             }
83             
84             $token = $this->getToken();
85             
86             $curlopts[CURLOPT_HTTPHEADER][] = 'Token: '.$token['token'];
87         }
88         
89         $dane = curl_init($address);
90         $curlopts[CURLOPT_RETURNTRANSFER] = TRUE;
91         $curlopts[CURLOPT_USERAGENT] = 'Bot Gadu-Gadu/'.main::VERSION.' (http://jacekk.info/botgg)';
92         $curlopts[CURLOPT_SSL_CIPHER_LIST] = 'HIGH:-MD5:-aNULL:-DES';
93         $curlopts[CURLOPT_SSL_VERIFYPEER] = TRUE;
94         $curlopts[CURLOPT_SSL_VERIFYHOST] = 2;
95         $curlopts[CURLOPT_CAPATH] = BOT_TOPDIR.'/data/ca-certificates/';
96         curl_setopt_array($dane, $curlopts);
97         $tok2 = $tok = curl_exec($dane);
98         $info = curl_getinfo($dane);
99         
fb87e0 100         if($parseXML) {
JK 101             try {
102                 libxml_use_internal_errors(TRUE);
103                 $tok = new SimpleXMLElement($tok);
104             }
105             catch(Exception $e) {
106                 throw new BotAPIGGXMLException('Otrzymano błędny XML od botmastera.', $tok2);
107             }
108             
109             if(!$tok) {
110                 if($info['http_code'] != 200) {
111                     throw new BotAPIGGHTTPException('Nie udało się wykonać zapytania HTTP.', $info['http_code'], $tok2);
112                 }
113                 else
114                 {
115                     throw new BotAPIGGXMLException('Otrzymano błędny XML od botmastera.', $tok2);
116                 }
117             }
8bd4d9 118         }
fb87e0 119         else
JK 120         {
8bd4d9 121             if($info['http_code'] != 200) {
JK 122                 throw new BotAPIGGHTTPException('Nie udało się wykonać zapytania HTTP.', $info['http_code'], $tok2);
123             }
124         }
125         
126         return $tok;
127     }
128     
129     function getToken($force = FALSE) {
fb87e0 130         if($force || self::$token === NULL) {
8bd4d9 131             $auth = $this->APIs['Gadu-Gadu'];
JK 132             
fb87e0 133             $tok = $this->httpQuery('https://botapi.gadu-gadu.pl/botmaster/getToken/'.$auth['numer'],  array(
8bd4d9 134                 CURLOPT_USERPWD => $auth['login'].':'.$auth['haslo'],
JK 135                 CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
fb87e0 136             ), FALSE);
8bd4d9 137             
JK 138             if($tok->errorMsg) {
139                 throw new BotAPIGGReplyException('Pobieranie tokena nie powiodło się.', $tok);
140             }
141             
fb87e0 142             self::$token = array('token' => (string)$tok->token, 'host' => (string)$tok->server, 'port' => (int)$tok->port);
8bd4d9 143         }
JK 144         
fb87e0 145         return self::$token;
8bd4d9 146     }
JK 147     
148     function setStatus($status, $desc = '') {
149         $auth = $this->APIs['Gadu-Gadu'];
150         $token = $this->getToken();
151         
fb87e0 152         $tok = $this->httpQuery('https://'.$token['host'].'/setStatus/'.$auth['numer'], array(
8bd4d9 153             CURLOPT_POST => TRUE,
09ac53 154             CURLOPT_POSTFIELDS => http_build_query(array(
fb87e0 155                 'status' => $status,
JK 156                 'desc' => $desc,
09ac53 157             ), '', '&'),
8bd4d9 158         ));
JK 159         
160         if( (string)$tok->status != '0') {
161             throw new BotAPIGGReplyException('Ustawianie statusu nie powiodło się.', $tok);
162         }
163     }
164     
165     function setUrl($url) {
166         $auth = $this->APIs['Gadu-Gadu'];
167         
fb87e0 168         $tok = $this->httpQuery('https://botapi.gadu-gadu.pl/botmaster/setUrl/'.$auth['numer'], array(
8bd4d9 169             CURLOPT_POST => TRUE,
JK 170             CURLOPT_POSTFIELDS => $url,
171         ));
172         
173         if( (string)$tok->status != '0') {
174             throw new BotAPIGGReplyException('Ustawianie adresu URL bota nie powiodło się.', $tok);
175         }
176         
177         return $tok;
178     }
179     
fb87e0 180     function getImage($hash) {
JK 181         $auth = $this->APIs['Gadu-Gadu'];
182         $token = $this->getToken();
183         
1e1a8d 184         $tok = $this->httpQuery('https://botapi.gadu-gadu.pl/botmaster/getImage/'.$auth['numer'], array(
fb87e0 185             CURLOPT_POST => TRUE,
09ac53 186             CURLOPT_POSTFIELDS => http_build_query(array('hash' => $hash), '', '&'),
fb87e0 187         ), TRUE, FALSE);
JK 188         
189         return $tok;
190     }
191     
c79ebe 192     function existsImage($hash) {
fb87e0 193         $auth = $this->APIs['Gadu-Gadu'];
JK 194         $token = $this->getToken();
195         
1e1a8d 196         $tok = $this->httpQuery('https://botapi.gadu-gadu.pl/botmaster/existsImage/'.$auth['numer'], array(
fb87e0 197             CURLOPT_POST => TRUE,
09ac53 198             CURLOPT_POSTFIELDS => http_build_query(array('hash' => $hash), '', '&'),
aea763 199         ));
fb87e0 200         
JK 201         if( (string)$tok->status != '0') {
202             return FALSE;
203         }
204         
205         return TRUE;
206     }
207     
208     function putImage($path) {
209         $auth = $this->APIs['Gadu-Gadu'];
210         $token = $this->getToken();
211         
1e1a8d 212         $tok = $this->httpQuery('https://botapi.gadu-gadu.pl/botmaster/putImage/'.$auth['numer'], array(
4cc259 213             CURLOPT_HTTPHEADER => array(
JK 214                 'Content-Type: image/x-any',
215                 'Expect: ',
216             ),
fb87e0 217             CURLOPT_POST => TRUE,
271560 218             CURLOPT_POSTFIELDS => file_get_contents($path),
aea763 219         ));
fb87e0 220         
JK 221         if( (string)$tok->status != '0') {
222             throw new BotAPIGGReplyException('Przesyłanie obrazka do botmastera nie powiodło się.', $tok);
223         }
224         
225         return (string)$tok->hash;
226     }
227     
8bd4d9 228     /**
JK 229      * Wysyła wiadomość do podanych użytkowników
230      * @param array $toURL Lista adresatów wiadomości w postaci: array('Gadu-Gadu://NUMER@gadu-gadu.pl', ...)
231      * @param BotMsg $msg Wiadomość do wysłania
232      * @param array $params Parametry przekazywane funkcji. Aktualnie dostępne:
233      * array( 'SendToOffline' => (bool)TRUE/FALSE )
234      */
235     function sendMessage($toURL, BotMsg $msg, $params = array()) {
1a5b21 236         if(is_string($toURL)) {
JK 237             $toURL = array($toURL);
238         }
239         
240         if(!is_array($toURL)) {
241             throw new Exception('Lista adresatów przekazywanych do funkcji BotAPIGG::sendMessage() winna być tablicą.');
242         }
243         
8bd4d9 244         $to = array();
JK 245         foreach($toURL as $url) {
246             $url = parse_url($url);
1a5b21 247             if($url === FALSE) {
JK 248                 continue;
249             }
250             
8bd4d9 251             if($url['scheme'] != 'Gadu-Gadu') {
JK 252                 continue;
253             }
254             
fb87e0 255             if($url['user'] == '' || !ctype_digit($url['user'])) {
8bd4d9 256                 throw new Exception('Nieznany użytkownik sieci Gadu-Gadu, któremu należy dostarczyć wiadomość.');
JK 257             }
258             
259             $to[] = $url['user'];
260         }
261         
262         if(empty($to)) {
263             return NULL;
264         }
265         
266         $msg = new BotMsgGG($msg);
267         
268         $auth = $this->APIs['Gadu-Gadu'];
269         $token = $this->getToken();
270         
271         $headers = array('Content-Type: application/x-www-form-urlencoded');
272         
273         if($params['SendToOffline'] == FALSE) {
274             $headers[] = 'Send-to-offline: 0';
275         }
276         
277         while(!empty($to)) {
278             $to_part = implode(',', array_splice($to, -5000));
279             
fb87e0 280             $tok = $this->httpQuery('https://'.$token['host'].'/sendMessage/'.$auth['numer'], array(
8bd4d9 281                 CURLOPT_HTTPHEADER => $headers,
JK 282                 CURLOPT_POST => TRUE,
fb87e0 283                 CURLOPT_POSTFIELDS => array(
JK 284                     'to' => $to_part,
285                     'msg' => $msg->getGG(FALSE),
286                 ),
8bd4d9 287             ));
JK 288             
1a5b21 289             // Brak obrazka w cache BotMastera...
8bd4d9 290             if((string)$tok->status == '18') {
1a5b21 291                 $tok = $this->httpQuery('https://'.$token['host'].'/sendMessage/'.$auth['numer'], array(
8bd4d9 292                     CURLOPT_HTTPHEADER => $headers,
JK 293                     CURLOPT_POST => TRUE,
fb87e0 294                     CURLOPT_POSTFIELDS => array(
JK 295                         'to' => $to_part,
296                         'msg' => $msg->getGG(TRUE),
297                     ),
8bd4d9 298                 ));
JK 299             }
300             
301             if((string)$tok->status != '0') {
302                 throw new BotAPIGGReplyException('Problemy przy wysyłaniu wiadomości do sieci Gadu-Gadu.', $tok);
303             }
304         }
305         
306         return TRUE;
307     }
1a5b21 308     
JK 309     /**
310      * Pobiera dane użytkownika z katalogu publicznego.
311      * @param string|BotUser Numer użytkownika
312      * @return array|false Tablica z danymi.
313      */
314     function getPublicData($number) {
315         if($number instanceof BotUser) {
316             if($number->network != 'gadu-gadu.pl') {
317                 return FALSE;
318             }
319             
320             $number = $number->uid;
321         }
322         
323         if(!ctype_digit($number)) {
324             throw new Exception('Numer użytkownika przekazany do funkcji BotAPIGG::getPublicData() jest niepoprawny.');
325         }
326         
327         try {
328             $data = file_get_contents('http://api.gadu-gadu.pl/users/'.$number.'.xml');
329             if(!$data) {
330                 throw new Exception('Nie udało się pobrać danych użytkownika z katalogu publicznego.');
331             }
332         }
333         catch(Exception $e) {
334             throw new Exception('Nie udało się pobrać danych użytkownika z katalogu publicznego.');
335         }
336         
337         libxml_use_internal_errors();
338         $data = simplexml_load_string($data);
339         libxml_clear_errors();
340         
341         if(!$data) {
342             throw new Exception('Dane użytkownika otrzymane z API Gadu-Gadu mają niepoprawny format.');
343         }
344         
345         if(!$data) {
346             throw new Exception('Dane użytkownika otrzymane z API Gadu-Gadu mają niepoprawny format.');
347         }
348         
349         
350         return (array)$data->users->user;
351     }
8bd4d9 352 }
JK 353 ?>