9 * This source file is subject to the new BSD license that is bundled
10 * with this package in the file LICENSE.
11 * It is also available through the world-wide-web at this URL:
12 * http://phergie.org/license
15 * @package Phergie_Plugin_Google
16 * @author Phergie Development Team <team@phergie.org>
17 * @copyright 2008-2010 Phergie Development Team (http://phergie.org)
18 * @license http://phergie.org/license New BSD License
19 * @link http://pear.phergie.org/package/Phergie_Plugin_Google
23 * Provides commands used to access several services offered by Google
24 * including search, translation, weather, maps, and currency and general
25 * value unit conversion.
28 * @package Phergie_Plugin_Google
29 * @author Phergie Development Team <team@phergie.org>
30 * @license http://phergie.org/license New BSD License
31 * @link http://pear.phergie.org/package/Phergie_Plugin_Google
32 * @uses Phergie_Plugin_Command pear.phergie.org
33 * @uses Phergie_Plugin_Http pear.phergie.org
34 * @uses Phergie_Plugin_Temperature pear.phergie.org
36 class Phergie_Plugin_Google extends Phergie_Plugin_Abstract
39 * Checks for dependencies.
43 public function onLoad()
45 $plugins = $this->getPluginHandler();
46 $plugins->getPlugin('Command');
47 $plugins->getPlugin('Http');
48 $plugins->getPlugin('Weather');
52 * Returns the first result of a Google search.
54 * @param string $query Search term
57 * @todo Implement use of URL shortening here
59 public function onCommandG($query)
61 $url = 'http://ajax.googleapis.com/ajax/services/search/web';
66 $response = $this->plugins->http->get($url, $params);
67 $json = $response->getContent()->responseData;
68 $event = $this->getEvent();
69 $source = $event->getSource();
70 $nick = $event->getNick();
71 if ($json->cursor->estimatedResultCount > 0) {
75 . $json->results[0]->titleNoFormatting
77 . $json->results[0]->url
79 . $json->cursor->moreResultsUrl;
80 $this->doPrivmsg($source, $msg);
82 $msg = $nick . ': No results for this query.';
83 $this->doPrivmsg($source, $msg);
88 * Performs a Google Count search for the given term.
90 * @param string $query Search term
94 public function onCommandGc($query)
96 $url = 'http://ajax.googleapis.com/ajax/services/search/web';
101 $response = $this->plugins->http->get($url, $params);
102 $json = $response->getContent()->responseData->cursor;
103 $count = $json->estimatedResultCount;
104 $event = $this->getEvent();
105 $source = $event->getSource();
106 $nick = $event->getNick();
110 number_format($count, 0) .
111 ' estimated results for ' . $query;
112 $this->doPrivmsg($source, $msg);
114 $this->doPrivmsg($source, $nick . ': No results for this query.');
119 * Performs a Google Translate search for the given term.
121 * @param string $from Language of the search term
122 * @param string $to Language to which the search term should be
124 * @param string $query Term to translate
128 public function onCommandGt($from, $to, $query)
130 $url = 'http://ajax.googleapis.com/ajax/services/language/translate';
134 'langpair' => $from . '|' . $to
136 $response = $this->plugins->http->get($url, $params);
137 $json = $response->getContent();
138 $event = $this->getEvent();
139 $source = $event->getSource();
140 $nick = $event->getNick();
141 if (empty($json->responseData->translatedText)) {
142 $this->doPrivmsg($source, $nick . ': ' . $json->responseDetails);
146 $nick . ': ' . $json->responseData->translatedText
152 * Performs a Google Weather search for the given term.
154 * @param string $location Location to search for
155 * @param int $offset Optional day offset from the current date
156 * between 0 and 3 to get the forecast
160 public function onCommandGw($location, $offset = null)
162 $url = 'http://www.google.com/ig/api';
164 'weather' => $location,
165 'hl' => $this->getConfig('google.lang', 'en'),
168 $response = $this->plugins->http->get($url, $params);
169 $xml = $response->getContent()->weather;
171 $event = $this->getEvent();
172 $source = $event->getSource();
174 if ($event->isInChannel()) {
175 $msg .= $event->getNick() . ': ';
178 if (isset($xml->problem_cause)) {
179 $msg .= $xml->problem_cause->attributes()->data[0];
180 $this->doPrivmsg($source, $msg);
184 $temperature = $this->plugins->getPlugin('Temperature');
186 $forecast = $xml->forecast_information;
187 $city = $forecast->city->attributes()->data[0];
188 $zip = $forecast->postal_code->attributes()->data[0];
190 if ($offset !== null) {
191 $offset = (int) $offset;
193 $this->doNotice($source, 'Past weather data is not available');
195 } elseif ($offset > 3) {
196 $this->doNotice($source, 'Future weather data is limited to 3 days from today');
200 $linha = $xml->forecast_conditions[$offset];
201 $low = $linha->low->attributes()->data[0];
202 $high = $linha->high->attributes()->data[0];
203 $units = $forecast->unit_system->attributes()->data[0];
204 $condition = $linha->condition->attributes()->data[0];
205 $day = $linha->day_of_week->attributes()->data[0];
207 $date = ($offset == 0) ? time() : strtotime('next ' . $day);
208 $day = ucfirst($day) . ' ' . date('n/j/y', $date);
210 if ($units == 'US') {
212 $lowC = $temperature->convertFahrenheitToCelsius($low);
214 $highC = $temperature->convertFahrenheitToCelsius($high);
217 $lowF = $temperature->convertCelsiusToFahrenheit($lowC);
219 $highF = $temperature->convertCelsiusToFahrenheit($high);
222 $msg .= 'Forecast for ' . $city . ' (' . $zip . ')'
223 . ' on ' . $day . ' ::'
224 . ' Low: ' . $lowF . 'F/' . $lowC . 'C,'
225 . ' High: ' . $highF . 'F/' . $highC . 'C,'
226 . ' Conditions: ' . $condition;
228 $conditions = $xml->current_conditions;
229 $condition = $conditions->condition->attributes()->data[0];
230 $tempF = $conditions->temp_f->attributes()->data[0];
231 $tempC = $conditions->temp_c->attributes()->data[0];
232 $humidity = $conditions->humidity->attributes()->data[0];
233 $wind = $conditions->wind_condition->attributes()->data[0];
234 $time = $forecast->current_date_time->attributes()->data[0];
235 $time = date('n/j/y g:i A', strtotime($time)) . ' +0000';
237 $hiF = $temperature->getHeatIndex($tempF, $humidity);
238 $hiC = $temperature->convertFahrenheitToCelsius($hiF);
240 $msg .= 'Weather for ' . $city . ' (' . $zip . ') -'
241 . ' Temperature: ' . $tempF . 'F/' . $tempC . 'C,'
242 . ' ' . $humidity . ','
243 . ' Heat Index: ' . $hiF . 'F/' . $hiC . 'C,'
244 . ' Conditions: ' . $condition . ','
245 . ' Updated: ' . $time;
248 $this->doPrivmsg($source, $msg);
252 * Performs a Google Maps search for the given term.
254 * @param string $location Location to search for
258 public function onCommandGmap($location)
260 $event = $this->getEvent();
261 $source = $event->getSource();
262 $nick = $event->getNick();
264 $location = utf8_encode($location);
265 $url = 'http://maps.google.com/maps/geo';
269 'gl' => $this->getConfig('google.lang', 'en'),
273 'key' => $this->getConfig('google.key')
275 $response = $this->plugins->http->get($url, $params);
276 $json = $response->getContent();
278 $qtd = count($json->Placemark);
281 foreach ($json->Placemark as $places) {
282 $xy = $places->Point->coordinates;
283 $address = utf8_decode($places->address);
284 $url = 'http://maps.google.com/maps?sll=' . $xy[1] . ','
286 $msg = $nick . ' -> ' . $address . ' - ' . $url;
287 $this->doPrivmsg($source, $msg);
292 ', there are a lot of places with that query.' .
293 ' Try to be more specific!';
294 $this->doPrivmsg($source, $msg);
296 } elseif ($qtd == 1) {
297 $xy = $json->Placemark[0]->Point->coordinates;
298 $address = utf8_decode($json->Placemark[0]->address);
299 $url = 'http://maps.google.com/maps?sll=' . $xy[1] . ',' . $xy[0]
301 $msg = $nick . ' -> ' . $address . ' - ' . $url;
302 $this->doPrivmsg($source, $msg);
304 $this->doPrivmsg($source, $nick . ', I found nothing.');
307 $this->doPrivmsg($source, $nick . ', we have a problem.');
312 * Perform a Google Convert query to convert a value from one metric to
315 * @param string $value Value to convert
316 * @param string $from Source metric
317 * @param string $to Destination metric
321 public function onCommandGconvert($value, $from, $to)
323 $url = 'http://www.google.com/finance/converter';
329 $response = $this->plugins->http->get($url, $params);
330 $contents = $response->getContent();
331 $event = $this->getEvent();
332 $source = $event->getSource();
333 $nick = $event->getNick();
335 libxml_use_internal_errors(true);
336 $doc = new DOMDocument;
337 $doc->loadHTML($contents);
338 libxml_clear_errors();
339 $xpath = new DOMXPath($doc);
340 $result = $xpath->query('//div[@id="currency_converter_result"]');
341 $div = $result->item(0);
342 $text = rtrim($div->textContent);
343 $this->doPrivmsg($source, $text);
348 * Performs a Google search to convert a value from one unit to another.
350 * @param string $query Query of the form "[quantity] [unit] to [unit2]"
354 * @pluginCmd [quantity] [unit] to [unit2] Convert a value from one
357 public function onCommandConvert($query)
359 $url = 'http://www.google.com/search?q=' . urlencode($query);
360 $response = $this->plugins->http->get($url);
361 $contents = $response->getContent();
362 $event = $this->getEvent();
363 $source = $event->getSource();
364 $nick = $event->getNick();
366 if ($response->isError()) {
367 $code = $response->getCode();
368 $message = $response->getMessage();
369 $this->doNotice($nick, 'ERROR: ' . $code . ' ' . $message);
373 $start = strpos($contents, '<h3 class=r>');
374 if ($start !== false) {
375 $end = strpos($contents, '</b>', $start);
376 $text = strip_tags(substr($contents, $start, $end - $start));
378 array(chr(195), chr(151), chr(160)),
385 $this->doPrivmsg($source, $nick . ': ' . $text);
387 $this->doNotice($nick, 'Sorry I couldn\'t find an answer.');
393 * Returns the first definition of a Google Dictionary search.
395 * @param string $query Word to get the definition
398 * @todo Implement use of URL shortening here
400 public function onCommandDefine($query)
402 $lang = $this->getConfig('google.lang', 'en');
403 $url = 'http://www.google.com/dictionary/json';
405 'callback' => 'result',
409 'restrict' => 'pr,de'
411 $response = $this->plugins->http->get($url, $params);
412 $json = $response->getContent();
414 // Remove some garbage from the JSON and decode it
415 $json = str_replace(array('result(', ',200,null)'), '', $json);
416 $json = str_replace('"', '¿?¿', $json);
417 $json = strip_tags(stripcslashes($json));
418 $json = str_replace('"', "'", $json);
419 $json = str_replace('¿?¿', '"', $json);
420 $json = json_decode($json);
422 $event = $this->getEvent();
423 $source = $event->getSource();
424 $nick = $event->getNick();
425 if (!empty($json->webDefinitions)) {
427 foreach ($json->primaries[0]->entries as $entry) {
428 if ($entry->type == 'meaning') {
431 foreach ($entry->terms as $term) {
432 if ($term->type == 'text') {
433 $text = trim($term->text);
439 $more = $results > 1 ? ($results - 1) . ' ' : '';
440 $lang_code = substr($lang, 0, 2);
441 $msg = $nick . ': ' . $text
442 . ' - You can find ' . $more . 'more results at '
443 . 'http://www.google.com/dictionary'
445 . '&langpair=' . $lang_code . '%7C' . $lang_code
447 . '&hl=' . $lang_code;
448 $this->doPrivmsg($source, $msg);
452 $this->onCommandDefine($query);
454 $msg = $nick . ': No results for this query.';
455 $this->doPrivmsg($source, $msg);