diff --git a/plugins/Irc/extlib/phergie/Phergie/Driver/Exception.php b/plugins/Irc/extlib/phergie/Phergie/Driver/Exception.php index aa2b838f7e..5873b2cb96 100755 --- a/plugins/Irc/extlib/phergie/Phergie/Driver/Exception.php +++ b/plugins/Irc/extlib/phergie/Phergie/Driver/Exception.php @@ -1,6 +1,6 @@ * @copyright 2008-2010 Phergie Development Team (http://phergie.org) @@ -22,7 +22,7 @@ /** * Exception related to driver operations. * - * @category Phergie + * @category Phergie * @package Phergie * @author Phergie Development Team * @license http://phergie.org/license New BSD License @@ -31,13 +31,13 @@ class Phergie_Driver_Exception extends Phergie_Exception { /** - * Error indicating that an operation was requested requiring an active + * Error indicating that an operation was requested requiring an active * connection before one had been set */ const ERR_NO_ACTIVE_CONNECTION = 1; /** - * Error indicating that an operation was requested requiring an active + * Error indicating that an operation was requested requiring an active * connection where one had been set but not initiated */ const ERR_NO_INITIATED_CONNECTION = 2; @@ -51,4 +51,9 @@ class Phergie_Driver_Exception extends Phergie_Exception * Error indicating that an attempt to send data via a connection failed */ const ERR_CONNECTION_WRITE_FAILED = 4; + + /** + * Error indicating that an attempt to read data via a connection failed + */ + const ERR_CONNECTION_READ_FAILED = 5; } diff --git a/plugins/Irc/extlib/phergie/Phergie/Driver/Streams.php b/plugins/Irc/extlib/phergie/Phergie/Driver/Streams.php index 1d0f1c5572..9f9e2585d2 100755 --- a/plugins/Irc/extlib/phergie/Phergie/Driver/Streams.php +++ b/plugins/Irc/extlib/phergie/Phergie/Driver/Streams.php @@ -221,6 +221,12 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract { // Check for a new event on the current connection $buffer = fgets($this->socket, 512); + if ($buffer === false) { + throw new Phergie_Driver_Exception( + 'Unable to read from socket', + Phergie_Driver_Exception::ERR_CONNECTION_READ_FAILED + ); + } // If no new event was found, return NULL if (empty($buffer)) { @@ -263,8 +269,9 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract case 'privmsg': case 'notice': - $ctcp = substr(strstr($args, ':'), 1); - if (substr($ctcp, 0, 1) === "\x01" && substr($ctcp, -1) === "\x01") { + $args = $this->parseArguments($args, 2); + list($source, $ctcp) = $args; + if (substr($ctcp, 0, 1) === "\001" && substr($ctcp, -1) === "\001") { $ctcp = substr($ctcp, 1, -1); $reply = ($cmd == 'notice'); list($cmd, $args) = array_pad(explode(' ', $ctcp, 2), 2, null); @@ -285,7 +292,7 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract } break; case 'action': - $args = array($this->getConnection()->getNick(), $args); + $args = array($source, $args); break; default: @@ -293,11 +300,9 @@ class Phergie_Driver_Streams extends Phergie_Driver_Abstract if ($reply) { $cmd .= 'Response'; } - $args = array($this->getConnection()->getNick(), $ctcp); + $args = array($source, $args); break; } - } else { - $args = $this->parseArguments($args, 2); } break; diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Beer/db.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Beer/db.php new file mode 100644 index 0000000000..309d389b55 --- /dev/null +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Beer/db.php @@ -0,0 +1,79 @@ +exec('CREATE TABLE beer (name VARCHAR(255), link VARCHAR(255))'); +$db->exec('CREATE UNIQUE INDEX beer_name ON beer (name)'); +$insert = $db->prepare('INSERT INTO beer (name, link) VALUES (:name, :link)'); + +// Get raw beerme.com data set +echo 'Downloading beerme.com data set', PHP_EOL; +$file = __DIR__ . '/beerlist.txt'; +if (!file_exists($file)) { + copy('http://beerme.com/beerlist.php', $file); +} +$contents = file_get_contents($file); + +// Extract data from data set +echo 'Processing beerme.com data', PHP_EOL; +$contents = tidy_repair_string($contents); +libxml_use_internal_errors(true); +$doc = new DOMDocument; +$doc->loadHTML($contents); +libxml_clear_errors(); +$xpath = new DOMXPath($doc); +$beers = $xpath->query('//table[@class="beerlist"]/tr/td[1]'); +$db->beginTransaction(); +foreach ($beers as $beer) { + $name = $beer->textContent; + $link = 'http://beerme.com' . $beer->childNodes->item(1)->getAttribute('href'); + $insert->execute(array($name, $link)); +} +$db->commit(); + +// Clean up +echo 'Cleaning up', PHP_EOL; +unlink($file); + +// Get and decompress openbeerdb.com data set +$archive = __DIR__ . '/beers.zip'; +if (!file_exists($archive)) { + echo 'Downloading openbeerdb.com data set', PHP_EOL; + copy('http://openbeerdb.googlecode.com/files/beers.zip', $archive); +} + +echo 'Decompressing openbeerdb.com data set', PHP_EOL; +$zip = new ZipArchive; +$zip->open($archive); +$zip->extractTo(__DIR__, 'beers/beers.csv'); +$zip->close(); +$file = __DIR__ . '/beers/beers.csv'; + +// Extract data from data set +echo 'Processing openbeerdb.com data', PHP_EOL; +$fp = fopen($file, 'r'); +$columns = fgetcsv($fp, 0, '|'); +$db->beginTransaction(); +while ($line = fgetcsv($fp, 0, '|')) { + $line = array_combine($columns, $line); + $name = $line['name']; + $link = null; + $insert->execute(array($name, $link)); +} +$db->commit(); +fclose($fp); + +// Clean up +echo 'Cleaning up', PHP_EOL; +unlink($file); +unlink($archive); +rmdir(__DIR__ . '/beers'); diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Encoding.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Encoding.php new file mode 100644 index 0000000000..419322bd7a --- /dev/null +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Encoding.php @@ -0,0 +1,182 @@ + + * @copyright 2008-2010 Phergie Development Team (http://phergie.org) + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_Encoding + */ + +/** + * Handles decoding markup entities and converting text between character + * encodings. + * + * @category Phergie + * @package Phergie_Plugin_Encoding + * @author Phergie Development Team + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_Encoding + */ +class Phergie_Plugin_Encoding extends Phergie_Plugin_Abstract +{ + /** + * Lookup table for entity conversions not supported by + * html_entity_decode() + * + * @var array + * @link http://us.php.net/manual/en/function.get-html-translation-table.php#73409 + * @link http://us.php.net/manual/en/function.get-html-translation-table.php#73410 + */ + protected static $entities = array( + 'α' => 913, + ''' => 39, + 'β' => 914, + '•' => 149, + 'χ' => 935, + 'ˆ' => 94, + 'δ' => 916, + 'ε' => 917, + 'η' => 919, + 'ƒ' => 402, + 'γ' => 915, + 'ι' => 921, + 'κ' => 922, + 'λ' => 923, + '“' => 147, + '‹' => 139, + '‘' => 145, + '—' => 151, + '−' => 45, + 'μ' => 924, + '–' => 150, + 'ν' => 925, + 'œ' => 140, + 'ω' => 937, + 'ο' => 927, + 'φ' => 934, + 'π' => 928, + 'ϖ' => 982, + 'ψ' => 936, + '”' => 148, + 'ρ' => 929, + '›' => 155, + '’' => 146, + 'š' => 138, + 'σ' => 931, + 'ς' => 962, + 'τ' => 932, + 'θ' => 920, + 'ϑ' => 977, + '˜' => 126, + '™' => 153, + 'ϒ' => 978, + 'υ' => 933, + 'ξ' => 926, + 'ÿ' => 159, + 'ζ' => 918, + ); + + /** + * Decodes markup entities in a given string. + * + * @param string $string String containing markup entities + * @param string $charset Optional character set name to use in decoding + * entities, defaults to UTF-8 + * + * @return string String with markup entities decoded + */ + public function decodeEntities($string, $charset = 'UTF-8') + { + $string = str_ireplace( + array_keys(self::$entities), + array_map('chr', self::$entities), + $string + ); + $string = html_entity_decode($string, ENT_QUOTES, $charset); + $string = preg_replace( + array('/�*([0-9]+);/me', '/�*([a-f0-9]+);/mei'), + array('$this->codeToUtf(\\1)', '$this->codeToUtf(hexdec(\\1))'), + $string + ); + return $string; + } + + /** + * Converts a given unicode to its UTF-8 equivalent. + * + * @param int $code Code to convert + * @return string Character corresponding to code + */ + public function codeToUtf8($code) + { + $code = (int) $code; + switch ($code) { + // 1 byte, 7 bits + case 0: + return chr(0); + case ($code & 0x7F): + return chr($code); + + // 2 bytes, 11 bits + case ($code & 0x7FF): + return chr(0xC0 | (($code >> 6) & 0x1F)) . + chr(0x80 | ($code & 0x3F)); + + // 3 bytes, 16 bits + case ($code & 0xFFFF): + return chr(0xE0 | (($code >> 12) & 0x0F)) . + chr(0x80 | (($code >> 6) & 0x3F)) . + chr(0x80 | ($code & 0x3F)); + + // 4 bytes, 21 bits + case ($code & 0x1FFFFF): + return chr(0xF0 | ($code >> 18)) . + chr(0x80 | (($code >> 12) & 0x3F)) . + chr(0x80 | (($code >> 6) & 0x3F)) . + chr(0x80 | ($code & 0x3F)); + } + } + + /** + * Transliterates characters in a given string where possible. + * + * @param string $string String containing characters to + * transliterate + * @param string $charsetFrom Optional character set of the string, + * defaults to UTF-8 + * @param string $charsetTo Optional character set to which the string + * should be converted, defaults to ISO-8859-1 + * + * @return string String with characters transliterated or the original + * string if transliteration was not possible + */ + public function transliterate($string, $charsetFrom = 'UTF-8', $charsetTo = 'ISO-8859-1') + { + // @link http://pecl.php.net/package/translit + if (function_exists('transliterate')) { + $string = transliterate($string, array('han_transliterate', 'diacritical_remove'), $charsetFrom, $charsetTo); + } elseif (function_exists('iconv')) { + $string = iconv($charsetFrom, $charsetTo . '//TRANSLIT', $string); + } else { + // @link http://stackoverflow.com/questions/1284535/php-transliteration/1285491#1285491 + $string = preg_replace( + '~&([a-z]{1,2})(acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml);~i', + '$1', + htmlentities($string, ENT_COMPAT, $charsetFrom) + ); + } + return $string; + } +} diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Google.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Google.php index 40c203a672..faa98f926a 100644 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Google.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Google.php @@ -1,6 +1,6 @@ * @copyright 2008-2010 Phergie Development Team (http://phergie.org) @@ -20,17 +20,18 @@ */ /** - * Provides commands used to access several services offered by Google - * including search, translation, weather, maps, and currency and general + * Provides commands used to access several services offered by Google + * including search, translation, weather, maps, and currency and general * value unit conversion. * - * @category Phergie + * @category Phergie * @package Phergie_Plugin_Google * @author Phergie Development Team * @license http://phergie.org/license New BSD License * @link http://pear.phergie.org/package/Phergie_Plugin_Google * @uses Phergie_Plugin_Command pear.phergie.org * @uses Phergie_Plugin_Http pear.phergie.org + * @uses Phergie_Plugin_Temperature pear.phergie.org * * @pluginDesc Provide access to some Google services */ @@ -44,6 +45,11 @@ class Phergie_Plugin_Google extends Phergie_Plugin_Abstract */ protected $http; + /** + * Language for Google Services + */ + protected $lang; + /** * Checks for dependencies. * @@ -55,6 +61,9 @@ class Phergie_Plugin_Google extends Phergie_Plugin_Abstract $plugins->getPlugin('Command'); $this->http = $plugins->getPlugin('Http'); $plugins->getPlugin('Help')->register($this); + $plugins->getPlugin('Weather'); + + $this->lang = $this->getConfig('google.lang', 'en'); } /** @@ -119,8 +128,8 @@ class Phergie_Plugin_Google extends Phergie_Plugin_Abstract $nick = $event->getNick(); if ($count) { $msg - = $nick . ': ' . - number_format($count, 0) . + = $nick . ': ' . + number_format($count, 0) . ' estimated results for ' . $query; $this->doPrivmsg($source, $msg); } else { @@ -132,7 +141,7 @@ class Phergie_Plugin_Google extends Phergie_Plugin_Abstract * Performs a Google Translate search for the given term. * * @param string $from Language of the search term - * @param string $to Language to which the search term should be + * @param string $to Language to which the search term should be * translated * @param string $query Term to translate * @@ -157,7 +166,7 @@ class Phergie_Plugin_Google extends Phergie_Plugin_Abstract $this->doPrivmsg($source, $nick . ': ' . $json->responseDetails); } else { $this->doPrivmsg( - $source, + $source, $nick . ': ' . $json->responseData->translatedText ); } @@ -165,51 +174,104 @@ class Phergie_Plugin_Google extends Phergie_Plugin_Abstract /** * Performs a Google Weather search for the given term. - * + * * @param string $location Location to search for + * @param int $offset Optional day offset from the current date + * between 0 and 3 to get the forecast * * @return void * * @pluginCmd [location] Show the weather for the specified location */ - public function onCommandGw($location) + public function onCommandGw($location, $offset = null) { $url = 'http://www.google.com/ig/api'; $params = array( 'weather' => $location, - 'hl' => 'pt-br', + 'hl' => $this->lang, 'oe' => 'UTF-8' ); $response = $this->http->get($url, $params); $xml = $response->getContent()->weather; - $source = $this->getEvent()->getSource(); - if (!isset($xml->problem_cause)) { - $city = $xml->forecast_information->city->attributes()->data[0]; - $time = $xml->forecast_information->current_date_time->attributes() - ->data[0]; - $condition = $xml->current_conditions->condition->attributes()->data[0]; - $temp = $xml->current_conditions->temp_c->attributes()->data[0] - . '� C'; - $humidity = $xml->current_conditions->humidity->attributes()->data[0]; - $wind = $xml->current_conditions->wind_condition->attributes()->data[0]; - $msg = implode(' - ', array($city, $temp, $condition, $humidity, $wind)); - $this->doPrivmsg($source, $msg); - foreach ($xml->forecast_conditions as $key => $linha) { - $day = ucfirst($linha->day_of_week->attributes()->data[0]); - $min = $linha->low->attributes()->data[0]; - $max = $linha->high->attributes()->data[0]; - $condition = $linha->condition->attributes()->data[0]; - $msg - = 'Forecast: ' . $day . - ' - Min: ' . $min . '� C' . - ' - Max: ' . $max . '� C' . - ' - ' . $condition; - $this->doPrivmsg($source, $msg); - } - } else { - $this->doPrivmsg($source, $xml->problem_cause->attributes()->data[0]); + $event = $this->getEvent(); + $source = $event->getSource(); + $msg = ''; + if ($event->isInChannel()) { + $msg .= $event->getNick() . ': '; } + + if (isset($xml->problem_cause)) { + $msg .= $xml->problem_cause->attributes()->data[0]; + $this->doPrivmsg($source, $msg); + return; + } + + $temperature = $this->plugins->getPlugin('Temperature'); + + $forecast = $xml->forecast_information; + $city = $forecast->city->attributes()->data[0]; + $zip = $forecast->postal_code->attributes()->data[0]; + + if ($offset !== null) { + $offset = (int) $offset; + if ($offset < 0) { + $this->doNotice($source, 'Past weather data is not available'); + return; + } elseif ($offset > 3) { + $this->doNotice($source, 'Future weather data is limited to 3 days from today'); + return; + } + + $linha = $xml->forecast_conditions[$offset]; + $low = $linha->low->attributes()->data[0]; + $high = $linha->high->attributes()->data[0]; + $units = $forecast->unit_system->attributes()->data[0]; + $condition = $linha->condition->attributes()->data[0]; + $day = $linha->day_of_week->attributes()->data[0]; + + $date = ($offset == 0) ? time() : strtotime('next ' . $day); + $day = ucfirst($day) . ' ' . date('n/j/y', $date); + + if ($units == 'US') { + $lowF = $low; + $lowC = $temperature->convertFahrenheitToCelsius($low); + $highF = $high; + $highC = $temperature->convertFahrenheitToCelsius($high); + } else { + $lowC = $low; + $lowF = $temperature->convertCelsiusToFahrenheit($lowC); + $highC = $high; + $highF = $temperature->convertCelsiusToFahrenheit($high); + } + + $msg .= 'Forecast for ' . $city . ' (' . $zip . ')' + . ' on ' . $day . ' ::' + . ' Low: ' . $lowF . 'F/' . $lowC . 'C,' + . ' High: ' . $highF . 'F/' . $highC . 'C,' + . ' Conditions: ' . $condition; + } else { + $conditions = $xml->current_conditions; + $condition = $conditions->condition->attributes()->data[0]; + $tempF = $conditions->temp_f->attributes()->data[0]; + $tempC = $conditions->temp_c->attributes()->data[0]; + $humidity = $conditions->humidity->attributes()->data[0]; + $wind = $conditions->wind_condition->attributes()->data[0]; + $time = $forecast->current_date_time->attributes()->data[0]; + $time = date('n/j/y g:i A', strtotime($time)) . ' +0000'; + + $hiF = $temperature->getHeatIndex($tempF, $humidity); + $hiC = $temperature->convertFahrenheitToCelsius($hiF); + + $msg .= 'Weather for ' . $city . ' (' . $zip . ') -' + . ' Temperature: ' . $tempF . 'F/' . $tempC . 'C,' + . ' ' . $humidity . ',' + . ' Heat Index: ' . $hiF . 'F/' . $hiC . 'C,' + . ' Conditions: ' . $condition . ',' + . ' Updated: ' . $time; + } + + $this->doPrivmsg($source, $msg); } /** @@ -222,23 +284,23 @@ class Phergie_Plugin_Google extends Phergie_Plugin_Abstract * @pluginCmd [location] Get the location from Google Maps to the location specified */ public function onCommandGmap($location) - { + { $event = $this->getEvent(); $source = $event->getSource(); $nick = $event->getNick(); - + $location = utf8_encode($location); $url = 'http://maps.google.com/maps/geo'; $params = array( 'q' => $location, 'output' => 'json', - 'gl' => 'br', + 'gl' => $this->lang, 'sensor' => 'false', 'oe' => 'utf8', 'mrt' => 'all', 'key' => $this->getConfig('google.key') ); - $response = $this->http->get($url, $params); + $response = $this->http->get($url, $params); $json = $response->getContent(); if (!empty($json)) { $qtd = count($json->Placemark); @@ -247,22 +309,22 @@ class Phergie_Plugin_Google extends Phergie_Plugin_Abstract foreach ($json->Placemark as $places) { $xy = $places->Point->coordinates; $address = utf8_decode($places->address); - $url = 'http://maps.google.com/maps?sll=' . $xy[1] . ',' + $url = 'http://maps.google.com/maps?sll=' . $xy[1] . ',' . $xy[0] . '&z=15'; $msg = $nick . ' -> ' . $address . ' - ' . $url; $this->doPrivmsg($source, $msg); } } else { $msg - = $nick . - ', there are a lot of places with that query.' . + = $nick . + ', there are a lot of places with that query.' . ' Try to be more specific!'; $this->doPrivmsg($source, $msg); } } elseif ($qtd == 1) { $xy = $json->Placemark[0]->Point->coordinates; $address = utf8_decode($json->Placemark[0]->address); - $url = 'http://maps.google.com/maps?sll=' . $xy[1] . ',' . $xy[0] + $url = 'http://maps.google.com/maps?sll=' . $xy[1] . ',' . $xy[0] . '&z=15'; $msg = $nick . ' -> ' . $address . ' - ' . $url; $this->doPrivmsg($source, $msg); @@ -275,7 +337,7 @@ class Phergie_Plugin_Google extends Phergie_Plugin_Abstract } /** - * Perform a Google Convert query to convert a value from one metric to + * Perform a Google Convert query to convert a value from one metric to * another. * * @param string $value Value to convert @@ -310,8 +372,8 @@ class Phergie_Plugin_Google extends Phergie_Plugin_Abstract } else { $str = str_replace('', '', $matches[0]); $str = str_replace($to . '', '', $str); - $text - = number_format($value, 2, ',', '.') . ' ' . $from . + $text + = number_format($value, 2, ',', '.') . ' ' . $from . ' => ' . number_format($str, 2, ',', '.') . ' ' . $to; $this->doPrivmsg($source, $text); } @@ -327,7 +389,7 @@ class Phergie_Plugin_Google extends Phergie_Plugin_Abstract * * @return void * - * @pluginCmd [quantity] [unit] to [unit2] Convert a value from one + * @pluginCmd [quantity] [unit] to [unit2] Convert a value from one * metric to another */ public function onCommandConvert($query) @@ -363,4 +425,61 @@ class Phergie_Plugin_Google extends Phergie_Plugin_Abstract $this->doNotice($nick, 'Sorry I couldn\'t find an answer.'); } } + + + /** + * Returns the first definition of a Google Dictionary search. + * + * @param string $query Word to get the definition + * + * @return void + * @todo Implement use of URL shortening here + * + * @pluginCmd [query] do a search of a definition on Google Dictionary + */ + public function onCommandDefine($query) + { + $query = urlencode($query); + $url = 'http://www.google.com/dictionary/json?callback=result'. + '&q='.$query.'&sl='.$this->lang.'&tl='.$this->lang. + '&restrict=pr,de'; + $json = file_get_contents($url); + + //Remove some garbage from the json + $json = str_replace(array("result(", ",200,null)"), "", $json); + + //Awesome workaround to remove a lot of slashes from json + $json = str_replace('"', '¿?¿', $json); + $json = strip_tags(stripcslashes($json)); + $json = str_replace('"', "'", $json); + $json = str_replace('¿?¿', '"', $json); + + $json = json_decode($json); + + $event = $this->getEvent(); + $source = $event->getSource(); + $nick = $event->getNick(); + if (!empty($json->webDefinitions)){ + $results = count($json->webDefinitions[0]->entries); + $more = $results > 1 ? ($results-1).' ' : NULL; + $lang_code = substr($this->lang, 0, 2); + $msg = + $nick . ': ' . + $json->webDefinitions[0]->entries[0]->terms[0]->text . + ' - You can find more '.$more.'results at '. + 'http://www.google.com/dictionary?aq=f&langpair='. + $lang_code.'%7C'.$lang_code.'&q='.$query.'&hl='.$lang_code; + $this->doPrivmsg($source, $msg); + }else{ + if ($this->lang != 'en'){ + $temp = $this->lang; + $this->lang = 'en'; + $this->onCommandDefine($query); + $this->lang = $temp; + }else{ + $msg = $nick . ': No results for this query.'; + $this->doPrivmsg($source, $msg); + } + } + } } diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Http.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Http.php index ae43b34c30..43c69eb879 100644 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Http.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Http.php @@ -1,6 +1,6 @@ * @copyright 2008-2010 Phergie Development Team (http://phergie.org) @@ -20,10 +20,10 @@ */ /** - * Provides an HTTP client for plugins to use in contacting web services or + * Provides an HTTP client for plugins to use in contacting web services or * retrieving feeds or web pages. * - * @category Phergie + * @category Phergie * @package Phergie_Plugin_Http * @author Phergie Development Team * @license http://phergie.org/license New BSD License @@ -46,7 +46,7 @@ class Phergie_Plugin_Http extends Phergie_Plugin_Abstract * @var array */ protected $handlers; - + /** * Initializes the handler lookup table. * @@ -55,8 +55,10 @@ class Phergie_Plugin_Http extends Phergie_Plugin_Abstract public function onLoad() { $this->handlers = array( - '(?:application|text)/xml(?:;.*)?' => 'simplexml_load_string', - '(?:(?:application|text)/(?:x-)?json)|text/javascript.*' => 'json_decode', + '(?:application|text)/xml(?:;.*)?' + => 'simplexml_load_string', + '(?:(?:application|text)/(?:x-)?json)|text/javascript.*' + => 'json_decode', ); if (is_array($this->config['http.handlers'])) { @@ -68,10 +70,10 @@ class Phergie_Plugin_Http extends Phergie_Plugin_Abstract } /** - * Sets a handler callback for a content type, which is called when a - * response of that content type is received to perform any needed - * transformations on the response body content before storing it in the - * response object. Note that the calling plugin is responsible for + * Sets a handler callback for a content type, which is called when a + * response of that content type is received to perform any needed + * transformations on the response body content before storing it in the + * response object. Note that the calling plugin is responsible for * indicating any dependencies related to specified handler callbacks. * * @param string $type PCRE regular expression (without delimiters) that @@ -96,12 +98,12 @@ class Phergie_Plugin_Http extends Phergie_Plugin_Abstract } /** - * Supporting method that parses the status line of an HTTP response + * Supporting method that parses the status line of an HTTP response * message. * * @param string $status Status line * - * @return array Associative array containing the HTTP version, response + * @return array Associative array containing the HTTP version, response * code, and response description */ protected function parseStatusLine($status) @@ -116,7 +118,7 @@ class Phergie_Plugin_Http extends Phergie_Plugin_Abstract } /** - * Supporting method that acts as an error handler to intercept HTTP + * Supporting method that acts as an error handler to intercept HTTP * responses resulting in PHP-level errors. * * @param int $errno Level of the error raised @@ -124,13 +126,13 @@ class Phergie_Plugin_Http extends Phergie_Plugin_Abstract * @param string $errfile Name of the file in which the error was raised * @param string $errline Line number on which the error was raised * - * @return bool Always returns TRUE to allow normal execution to + * @return bool Always returns TRUE to allow normal execution to * continue once this method terminates */ - protected function handleError($errno, $errstr, $errfile, $errline) + public function handleError($errno, $errstr, $errfile, $errline) { if ($httperr = strstr($errstr, 'HTTP/')) { - $parts = $this->parseStatusLine($httperr); + $parts = $this->parseStatusLine($httperr); $this->response ->setCode($parts['code']) ->setMessage($parts['message']); @@ -143,9 +145,9 @@ class Phergie_Plugin_Http extends Phergie_Plugin_Abstract * Supporting method that executes a request and handles the response. * * @param string $url URL to request - * @param array $context Associative array of stream context parameters + * @param array $context Associative array of stream context parameters * - * @return Phergie_Plugin_Http_Response Object representing the response + * @return Phergie_Plugin_Http_Response Object representing the response * resulting from the request */ public function request($url, array $context) @@ -164,6 +166,9 @@ class Phergie_Plugin_Http extends Phergie_Plugin_Abstract $message = $status['message']; $headers = array(); foreach (array_slice($meta['wrapper_data'], 1) as $header) { + if (!strpos($header, ':')) { + continue; + } list($name, $value) = explode(': ', $header, 2); $headers[$name] = $value; } @@ -174,7 +179,7 @@ class Phergie_Plugin_Http extends Phergie_Plugin_Abstract ->setMessage($message) ->setHeaders($headers) ->setMeta($meta); - + $body = stream_get_contents($stream); $type = $this->response->getHeaders('content-type'); foreach ($this->handlers as $expr => $handler) { @@ -218,7 +223,7 @@ class Phergie_Plugin_Http extends Phergie_Plugin_Abstract * @param string $url URL for the request * @param array $query Optional associative array of parameters * constituting the URL query string if $url has none - * @param array $context Optional associative array of additional stream + * @param array $context Optional associative array of additional stream * context parameters * * @return Phergie_Plugin_Http_Response Received response data @@ -238,25 +243,26 @@ class Phergie_Plugin_Http extends Phergie_Plugin_Abstract * Performs a POST request. * * @param string $url URL for the request - * @param array $query Optional associative array of parameters + * @param array $query Optional associative array of parameters * constituting the URL query string if $url has none - * @param array $post Optional associative array of parameters - * constituting the POST request body if it is using the + * @param array $post Optional associative array of parameters + * constituting the POST request body if it is using the * traditional URL-encoded format - * @param array $context Optional associative array of additional stream + * @param array $context Optional associative array of additional stream * context parameters * * @return Phergie_Plugin_Http_Response Received response data */ - public function post($url, array $query = array(), array $post = array(), array $context = array()) - { + public function post($url, array $query = array(), + array $post = array(), array $context = array() + ) { if (!empty($params)) { $url .= '?' . http_build_query($query); } $context['method'] = 'POST'; - if (!empty($post) + if (!empty($post) && (!empty($context['header']) xor stripos($context['header'], 'Content-Type')) ) { @@ -265,7 +271,7 @@ class Phergie_Plugin_Http extends Phergie_Plugin_Abstract } else { $context['header'] = ''; } - $context['header'] .= + $context['header'] .= 'Content-Type: application/x-www-form-urlencoded'; $context['content'] = http_build_query($post); } diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Http/Response.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Http/Response.php index 80d16c4b85..b9e377cf64 100644 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Http/Response.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Http/Response.php @@ -1,6 +1,6 @@ * @copyright 2008-2010 Phergie Development Team (http://phergie.org) @@ -20,9 +20,9 @@ */ /** - * Data structure for HTTP response information. + * Data structure for HTTP response information. * - * @category Phergie + * @category Phergie * @package Phergie_Plugin_Http * @author Phergie Development Team * @license http://phergie.org/license New BSD License @@ -33,7 +33,7 @@ class Phergie_Plugin_Http_Response /** * HTTP response code or 0 if no HTTP response was received * - * @var string + * @var string */ protected $code; @@ -42,7 +42,7 @@ class Phergie_Plugin_Http_Response * * @var array */ - protected $codeStrings = array( + protected static $codeStrings = array( 0 => 'No Response', 100 => 'Continue', 200 => 'OK', @@ -75,7 +75,7 @@ class Phergie_Plugin_Http_Response ); /** - * Description of the HTTP response code or the error message if no HTTP + * Description of the HTTP response code or the error message if no HTTP * response was received * * @var string @@ -135,11 +135,11 @@ class Phergie_Plugin_Http_Response { $code = $this->code; - if (!isset($this->codeStrings[$code])) { + if (!isset(self::$codeStrings[$code])) { return 'Unkown HTTP Status'; } - return $this->codeStrings[$code]; + return self::$codeStrings[$code]; } /** @@ -198,7 +198,7 @@ class Phergie_Plugin_Http_Response /** * Returns the content of the response body. * - * @return mixed Response body content, decoded for supported content + * @return mixed Response body content, decoded for supported content * types */ public function getContent() @@ -209,7 +209,7 @@ class Phergie_Plugin_Http_Response /** * Sets the response headers. * - * @param array $headers Associative array of response headers indexed + * @param array $headers Associative array of response headers indexed * by header name * * @return Phergie_Plugin_Http_Response Provides a fluent interface @@ -223,14 +223,14 @@ class Phergie_Plugin_Http_Response } /** - * Returns all response headers or the value of a single specified + * Returns all response headers or the value of a single specified * response header. * - * @param string $name Optional name of a single header for which the + * @param string $name Optional name of a single header for which the * associated value should be returned * - * @return array|string Associative array of all header values, a string - * containing the value of the header indicated by $name if one + * @return array|string Associative array of all header values, a string + * containing the value of the header indicated by $name if one * is set, or null if one is not */ public function getHeaders($name = null) @@ -261,11 +261,11 @@ class Phergie_Plugin_Http_Response /** * Returns all metadata or the value of a single specified metadatum. * - * @param string $name Optional name of a single metadatum for which the + * @param string $name Optional name of a single metadatum for which the * associated value should be returned - * - * @return array|string|null Associative array of all metadata values, a - * string containing the value of the metadatum indicated by + * + * @return array|string|null Associative array of all metadata values, a + * string containing the value of the metadatum indicated by * $name if one is set, or null if one is not */ public function getMeta($name = null) diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Lart.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Lart.php new file mode 100644 index 0000000000..d00cae0dd1 --- /dev/null +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Lart.php @@ -0,0 +1,303 @@ + + * @copyright 2008-2010 Phergie Development Team (http://phergie.org) + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_Lart + */ + +/** + * Accepts terms and corresponding definitions for storage to a local data + * source and performs and returns the result of lookups for term definitions + * as they are requested. + * + * @category Phergie + * @package Phergie_Plugin_Lart + * @author Phergie Development Team + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_Lart + * @uses Phergie_Plugin_Command pear.phergie.org + * @uses extension PDO + * @uses extension pdo_sqlite + */ +class Phergie_Plugin_Lart extends Phergie_Plugin_Abstract +{ + /** + * PDO instance for the database + * + * @var PDO + */ + protected $db; + + /** + * Prepared statement for inserting a new definition + * + * @var PDOStatement + */ + protected $save; + + /** + * Prepared statement for deleting the definition for a given term + * + * @var PDOStatement + */ + protected $delete; + + /** + * Prepared statement for searching for a definition for which the term + * matches as a regular expression against a given search string + * + * @var PDOStatement + */ + protected $process; + + /** + * Prepared statement for searching for a definition by its exact term + * + * @var PDOStatement + */ + protected $select; + + /** + * Checks for dependencies and initializes the database. + * + * @return void + */ + public function onLoad() + { + if (!extension_loaded('PDO') || !extension_loaded('pdo_sqlite')) { + $this->fail('PDO and pdo_sqlite extensions must be installed'); + } + + $this->plugins->getPlugin('Command'); + + $dir = dirname(__FILE__) . '/' . $this->getName(); + $path = $dir . '/lart.db'; + $exists = file_exists($path); + if (!$exists) { + mkdir($dir); + } + + try { + $this->db = new PDO('sqlite:' . $path); + } catch (PDO_Exception $e) { + throw new Phergie_Plugin_Exception($e->getMessage()); + } + + $this->db->sqliteCreateFunction('preg_match', 'preg_match'); + + if (!$exists) { + $this->db->exec(' + CREATE TABLE lart ( + name VARCHAR(255), + definition TEXT, + hostmask VARCHAR(50), + tstamp VARCHAR(19) + ) + '); + $this->db->exec(' + CREATE UNIQUE INDEX lart_name ON lart (name) + '); + } + + $this->save = $this->db->prepare(' + REPLACE INTO lart (name, definition, hostmask, tstamp) + VALUES (:name, :definition, :hostmask, :tstamp) + '); + + $this->process = $this->db->prepare(' + SELECT * + FROM lart + WHERE preg_match(name, :name) + '); + + $this->select = $this->db->prepare(' + SELECT * + FROM lart + WHERE name = :name + '); + + $this->delete = $this->db->prepare(' + DELETE FROM lart + WHERE name = :name + '); + } + + /** + * Retrieves the definition for a given term if it exists. + * + * @param string $term Term to search for + * + * @return mixed String containing the definition or FALSE if no definition + * exists + */ + protected function getLart($term) + { + $this->process->execute(array(':name' => $term)); + $row = $this->process->fetchObject(); + if ($row === false) { + return false; + } + preg_match($row->name, $term, $match); + $definition = preg_replace( + "/(?:\\\\|\\$)([0-9]+)/e", + '$match[\1]', + $row->definition + ); + $event = $this->getEvent(); + $definition = str_replace( + array('$source', '$nick'), + array($event->getSource(), $event->getNick()), + $definition + ); + return $definition; + } + + /** + * Deletes a given definition. + * + * @param string $term Term for which the definition should be deleted + * + * @return boolean TRUE if the definition was found and deleted, FALSE + * otherwise + */ + protected function deleteLart($term) + { + $this->delete->execute(array(':name' => $term)); + return ($this->delete->rowCount() > 0); + } + + /** + * Saves a given definition. + * + * @param string $term Term to trigger a response containing the + * corresponding definition, may be a regular expression + * @param string $definition Definition corresponding to the term + * + * @return boolean TRUE if the definition was saved successfully, FALSE + * otherwise + */ + protected function saveLart($term, $definition) + { + $data = array( + ':name' => $term, + ':definition' => $definition, + ':hostmask' => (string) $this->getEvent()->getHostmask(), + ':tstamp' => time() + ); + $this->save->execute($data); + return ($this->save->rowCount() > 0); + } + + /** + * Returns information about a definition. + * + * @param string $term Term about which to return information + * + * @return void + */ + public function onCommandLartinfo($term) + { + $this->select->execute(array(':name' => $term)); + $row = $this->select->fetchObject(); + $msg = $this->getEvent()->getNick() . ': '; + if (!$row) { + $msg .= 'Lart not found'; + } else { + $msg .= 'Term: ' . $row->name + . ', Definition: ' . $row->definition + . ', User: ' . $row->hostmask + . ', Added: ' . date('n/j/y g:i A', $row->tstamp); + } + $this->doNotice($this->getEvent()->getSource(), $msg); + } + + /** + * Creates a new definition. + * + * @param string $term Term to add + * @param string $definition Definition to add + * + * @return void + */ + public function onCommandAddlart($term, $definition) + { + $result = $this->saveLart($term, $definition); + if ($result) { + $msg = 'Lart saved successfully'; + } else { + $msg = 'Lart could not be saved'; + } + $this->doNotice($this->getEvent()->getSource(), $msg); + } + + /** + * Removes an existing definition. + * + * @param string $term Term for which the definition should be removed + * + * @return void + */ + public function onCommandDeletelart($term) + { + $source = $this->getEvent()->getSource(); + if ($this->deleteLart($term)) { + $msg = 'Lart deleted successfully'; + } else { + $msg = 'Lart not found'; + } + $this->doNotice($source, $msg); + } + + /** + * Processes definition triggers in the text of the current event. + * + * @return void + */ + protected function processLart() + { + $lart = $this->getLart($this->getEvent()->getText()); + if ($lart) { + if (strpos($lart, '/me') === 0) { + $lart = substr($lart, 4); + $method = 'doAction'; + } else { + $method = 'doPrivmsg'; + } + $this->$method($this->getEvent()->getSource(), $lart); + } + } + + /** + * Processes definition triggers in messages. + * + * @return void + */ + public function onPrivmsg() + { + $this->processLart(); + } + + /** + * Processes definition triggers in CTCP actions. + * + * @return void + */ + public function onAction() + { + $this->processLart(); + } +} diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/NickServ.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/NickServ.php index f873c753bb..e97abecf78 100644 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/NickServ.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/NickServ.php @@ -57,16 +57,13 @@ class Phergie_Plugin_NickServ extends Phergie_Plugin_Abstract $this->getPluginHandler()->getPlugin('Command'); // Get the name of the NickServ bot, defaults to NickServ - $this->botNick = $this->config['nickserv.botnick']; - if (!$this->botNick) { - $this->botNick = 'NickServ'; - } + $this->botNick = $this->getConfig('nickserv.botnick', 'NickServ'); // Get the identify message - $this->identifyMessage = $this->config['nickserv.identify_message']; - if (!$this->identifyMessage) { - $this->identifyMessage = '/This nickname is registered./'; - } + $this->identifyMessage = $this->getConfig( + 'nickserv.identify_message', + '/This nickname is registered./' + ); } /** diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Remind.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Remind.php index cfb3c07e8c..42d674c68f 100644 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Remind.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Remind.php @@ -30,6 +30,8 @@ * @link http://pear.phergie.org/package/Phergie_Plugin_Remind * @uses Phergie_Plugin_Command pear.phergie.org * @uses Phergie_Plugin_Time pear.phergie.org + * @uses extension PDO + * @uses extension pdo_sqlite */ class Phergie_Plugin_Remind extends Phergie_Plugin_Abstract { @@ -67,15 +69,11 @@ class Phergie_Plugin_Remind extends Phergie_Plugin_Abstract $plugins = $this->getPluginHandler(); $plugins->getPlugin('Command'); $plugins->getPlugin('Time'); - } - /** - * Creates the database if it does not already exist. - * - * @return void - */ - public function onConnect() - { + if (!extension_loaded('PDO') || !extension_loaded('pdo_sqlite')) { + $this->fail('PDO and pdo_sqlite extensions must be installed'); + } + $dir = dirname(__FILE__) . '/' . $this->getName(); $path = $dir . '/reminder.db'; if (!file_exists($dir)) { diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Temperature.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Temperature.php new file mode 100644 index 0000000000..541fd85cff --- /dev/null +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Temperature.php @@ -0,0 +1,81 @@ + + * @copyright 2008-2010 Phergie Development Team (http://phergie.org) + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_Temperature + */ + +/** + * Performs temperature calculations for other plugins. + * + * @category Phergie + * @package Phergie_Plugin_Temperature + * @author Phergie Development Team + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_Temperature + */ +class Phergie_Plugin_Temperature extends Phergie_Plugin_Abstract +{ + /** + * Converts a temperature in Celsius to Fahrenheit. + * + * @param int $temp Temperature in Celsius + * + * @return int Temperature converted to Fahrenheit + */ + public function convertCelsiusToFahrenheit($temp) + { + return round(((((int) $temp * 9) / 5) + 32)); + } + + /** + * Converts a temperature in Fahrenheit to Celsius. + * + * @param int $temp Temperature in Fahrenheit + * + * @return int Temperature converted to Celsius + */ + public function convertFahrenheitToCelsius($temp) + { + return round(((((int) $temp - 32) * 5) / 9)); + } + + /** + * Calculates the heat index (i.e. "feels like" temperature) based on + * temperature and relative humidity. + * + * @param int $temperature Temperature in degrees Fahrenheit + * @param int $humidity Relative humidity (ex: 68) + * @return int Heat index in degrees Fahrenheit + */ + public function getHeatIndex($temperature, $humidity) + { + $temperature2 = $temperature * $temperature; + $humidity2 = $humidity * $humidity; + return round( + -42.379 + + (2.04901523 * $temperature) + + (10.14333127 * $humidity) - + (0.22475541 * $temperature * $humidity) - + (0.00683783 * $temperature2) - + (0.05481717 * $humidity2) + + (0.00122874 * $temperature2 * $humidity) + + (0.00085282 * $temperature * $humidity2) - + (0.00000199 * $temperature2 * $humidity2) + ); + } +} diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Tld.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Tld.php index 5efc265c64..21993f73c5 100644 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Tld.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Tld.php @@ -29,7 +29,6 @@ * @author Phergie Development Team * @license http://phergie.org/license New BSD License * @link http://pear.phergie.org/package/Phergie_Plugin_Tld - * @uses Phergie_Plugin_Http pear.phergie.org * @uses extension PDO * @uses extension pdo_sqlite * @@ -42,11 +41,6 @@ class Phergie_Plugin_Tld extends Phergie_Plugin_Abstract * @var PDO */ protected $db; - /** - * Some fixed TLD values, keys must be lowercase - * @var array - */ - protected static $fixedTlds; /** * Prepared statement for selecting a single tld @@ -67,19 +61,13 @@ class Phergie_Plugin_Tld extends Phergie_Plugin_Abstract */ public function onLoad() { + if (!extension_loaded('PDO') || !extension_loaded('pdo_sqlite')) { + $this->fail('PDO and pdo_sqlite extensions must be installed'); + } + $help = $this->getPluginHandler()->getPlugin('Help'); $help->register($this); - if (!is_array(self::$fixedTlds)) { - self::$fixedTlds = array( - 'phergie' => 'You can find Phergie at http://www.phergie.org', - 'spoon' => 'Don\'t you know? There is no spoon!', - 'poo' => 'Do you really think that\'s funny?', - 'root' => 'Diagnostic marker to indicate ' - . 'a root zone load was not truncated.' - ); - } - $dbFile = dirname(__FILE__) . '/Tld/tld.db'; try { $this->db = new PDO('sqlite:' . $dbFile); @@ -124,19 +112,15 @@ class Phergie_Plugin_Tld extends Phergie_Plugin_Abstract * * @param string $tld TLD to search for * - * @return string Definition of the given TLD + * @return mixed Definition of the given TLD as a string or false if unknown */ public function getTld($tld) { $tld = trim(strtolower($tld)); - if (isset(self::$fixedTlds[$tld])) { - return self::$fixedTlds[$tld]; - } else { - if ($this->select->execute(array('tld' => $tld))) { - $tlds = $this->select->fetch(); - if (is_array($tlds)) { - return '(' . $tlds['type'] . ') ' . $tlds['description']; - } + if ($this->select->execute(array('tld' => $tld))) { + $tlds = $this->select->fetch(); + if (is_array($tlds)) { + return '(' . $tlds['type'] . ') ' . $tlds['description']; } } return false; @@ -145,7 +129,8 @@ class Phergie_Plugin_Tld extends Phergie_Plugin_Abstract /** * Retrieves a list of all the TLDs and their definitions * - * @return array Array of all the TLDs and their definitions + * @return mixed Array of all the TLDs and their definitions or FALSE on + * failure */ public function getTlds() { @@ -159,7 +144,6 @@ class Phergie_Plugin_Tld extends Phergie_Plugin_Abstract . $tld['description']; } } - unset($tlds); return $tldinfo; } } diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Url.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Url.php index 2ea33befdf..bac115b1b9 100644 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Url.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Url.php @@ -31,7 +31,9 @@ * @author Phergie Development Team * @license http://phergie.org/license New BSD License * @link http://pear.phergie.org/package/Phergie_Plugin_Url + * @uses Phergie_Plugin_Encoding pear.phergie.org * @uses Phergie_Plugin_Http pear.phergie.org + * @uses Phergie_Plugin_Tld pear.phergie.org */ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract { @@ -121,50 +123,6 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract */ protected $detectSchemeless = false; - /** - * List of error messages to return when the requested URL returns an - * HTTP error - * - * @var array - */ - protected $httpErrors = array( - 100 => '100 Continue', - 200 => '200 OK', - 201 => '201 Created', - 204 => '204 No Content', - 206 => '206 Partial Content', - 300 => '300 Multiple Choices', - 301 => '301 Moved Permanently', - 302 => '302 Found', - 303 => '303 See Other', - 304 => '304 Not Modified', - 307 => '307 Temporary Redirect', - 400 => '400 Bad Request', - 401 => '401 Unauthorized', - 403 => '403 Forbidden', - 404 => '404 Not Found', - 405 => '405 Method Not Allowed', - 406 => '406 Not Acceptable', - 408 => '408 Request Timeout', - 410 => '410 Gone', - 413 => '413 Request Entity Too Large', - 414 => '414 Request URI Too Long', - 415 => '415 Unsupported Media Type', - 416 => '416 Requested Range Not Satisfiable', - 417 => '417 Expectation Failed', - 500 => '500 Internal Server Error', - 501 => '501 Method Not Implemented', - 503 => '503 Service Unavailable', - 506 => '506 Variant Also Negotiates' - ); - - /** - * An array containing a list of TLDs used for non-scheme matches - * - * @var array - */ - protected $tldList = array(); - /** * Shortener object */ @@ -176,12 +134,17 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract protected $renderers = array(); /** - * Initializes settings, checks dependencies. + * Checks for dependencies. * * @return void */ - public function onConnect() + public function onLoad() { + $plugins = $this->plugins; + $plugins->getPlugin('Encoding'); + $plugins->getPlugin('Http'); + $plugins->getPlugin('Tld'); + // make the shortener configurable $shortener = $this->getConfig('url.shortener', 'Trim'); $shortener = "Phergie_Plugin_Url_Shorten_{$shortener}"; @@ -191,14 +154,6 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract $this->fail("Declared shortener class {$shortener} is not of proper ancestry"); } - // Get a list of valid TLDs - if (!is_array($this->tldList) || count($this->tldList) <= 6) { - $tldPath = dirname(__FILE__) . '/Url/url.tld.txt'; - $this->tldList = explode("\n", file_get_contents($tldPath)); - $this->debug('Loaded ' . count($this->tldList) . ' tlds'); - rsort($this->tldList); - } - // load config (a bit ugly, but focusing on porting): foreach ( array( @@ -226,16 +181,130 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract * @return void */ public function onPrivmsg() + { + $this->handleMsg(); + } + + /** + * Checks an incoming message for the presence of a URL and, if one is + * found, responds with its title if it is an HTML document and the + * shortened equivalent of its original URL if it meets length requirements. + * + * @todo Update this to pull configuration settings from $this->config + * rather than caching them as class properties + * @return void + */ + public function onAction() + { + $this->handleMsg(); + } + + /** + * Handles message events and responds with url titles. + * + * @return void + */ + protected function handleMsg() { $source = $this->getEvent()->getSource(); $user = $this->getEvent()->getNick(); + $responses = array(); + $urls = $this->findUrls($this->getEvent()->getArgument(1)); + + foreach ($urls as $parsed) { + $url = $parsed['glued']; + + // allow out-of-class renderers to handle this URL + foreach ($this->renderers as $renderer) { + if ($renderer->renderUrl($parsed) === true) { + // renderers should return true if they've fully + // rendered the passed URL (they're responsible + // for their own output) + $this->debug('Handled by renderer: ' . get_class($renderer)); + continue 2; + } + } + + // Convert url + $shortenedUrl = $this->shortener->shorten($url); + if (!$shortenedUrl) { + $this->debug('Invalid Url: Unable to shorten. (' . $url . ')'); + $shortenedUrl = $url; + } + + // Prevent spamfest + if ($this->checkUrlCache($url, $shortenedUrl)) { + $this->debug('Invalid Url: URL is in the cache. (' . $url . ')'); + continue; + } + + $title = $this->getTitle($url); + if (!empty($title)) { + $responses[] = str_replace( + array( + '%title%', + '%link%', + '%nick%' + ), array( + $title, + $shortenedUrl, + $user + ), $this->messageFormat + ); + } + + // Update cache + $this->updateUrlCache($url, $shortenedUrl); + unset($title, $shortenedUrl, $title); + } + + // Check to see if there were any URL responses, format them and handle if they + // get merged into one message or not + if (count($responses) > 0) { + if ($this->mergeLinks) { + $message = str_replace( + array( + '%message%', + '%nick%' + ), array( + implode('; ', $responses), + $user + ), $this->baseFormat + ); + $this->doPrivmsg($source, $message); + } else { + foreach ($responses as $response) { + $message = str_replace( + array( + '%message%', + '%nick%' + ), array( + implode('; ', $responses), + $user + ), $this->baseFormat + ); + $this->doPrivmsg($source, $message); + } + } + } + } + + /** + * Detect URLs in a given string. + * + * @param string $message the string to detect urls in + * + * @return array the array of urls found + */ + public function findUrls($message) + { $pattern = '#'.($this->detectSchemeless ? '' : 'https?://').'(?:([0-9]{1,3}(?:\.[0-9]{1,3}){3})(?![^/]) | (' .($this->detectSchemeless ? '(?getEvent()->getArgument(1), $matches, PREG_SET_ORDER)) { - $responses = array(); + if (preg_match_all($pattern, $message, $matches, PREG_SET_ORDER)) { foreach ($matches as $m) { $url = trim(rtrim($m[0], ', ].?!;')); @@ -251,17 +320,6 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract continue; } - // allow out-of-class renderers to handle this URL - foreach ($this->renderers as $renderer) { - if ($renderer->renderUrl($parsed) === true) { - // renderers should return true if they've fully - // rendered the passed URL (they're responsible - // for their own output) - $this->debug('Handled by renderer: ' . get_class($renderer)); - continue 2; - } - } - // Check to see if the given IP/Host is valid if (!empty($m[1]) and !$this->checkValidIP($m[1])) { $this->debug('Invalid Url: ' . $m[1] . ' is not a valid IP address. (' . $url . ')'); @@ -275,7 +333,7 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract $parsed['tld'] = ($pos !== false ? substr($parsed['host'], ($pos+1)) : ''); // Check to see if the URL has a valid TLD - if (is_array($this->tldList) && !in_array(strtolower($parsed['tld']), $this->tldList)) { + if ($this->plugins->tld->getTld($parsed['tld']) === false) { $this->debug('Invalid Url: ' . $parsed['tld'] . ' is not a supported TLD. (' . $url . ')'); continue; } @@ -295,73 +353,12 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract $this->debug('Invalid Url: ' . $parsed['scheme'] . ' is not a supported scheme. (' . $url . ')'); continue; } - $url = $this->glueURL($parsed); - unset($parsed); - // Convert url - $shortenedUrl = $this->shortener->shorten($url); - if (!$shortenedUrl) { - $this->debug('Invalid Url: Unable to shorten. (' . $url . ')'); - continue; - } - - // Prevent spamfest - if ($this->checkUrlCache($url, $shortenedUrl)) { - $this->debug('Invalid Url: URL is in the cache. (' . $url . ')'); - continue; - } - - $title = self::getTitle($url); - if (!empty($title)) { - $responses[] = str_replace( - array( - '%title%', - '%link%', - '%nick%' - ), array( - $title, - $shortenedUrl, - $user - ), $this->messageFormat - ); - } - - // Update cache - $this->updateUrlCache($url, $shortenedUrl); - unset($title, $shortenedUrl, $title); - } - /** - * Check to see if there were any URL responses, format them and handle if they - * get merged into one message or not - */ - if (count($responses) > 0) { - if ($this->mergeLinks) { - $message = str_replace( - array( - '%message%', - '%nick%' - ), array( - implode('; ', $responses), - $user - ), $this->baseFormat - ); - $this->doPrivmsg($source, $message); - } else { - foreach ($responses as $response) { - $message = str_replace( - array( - '%message%', - '%nick%' - ), array( - implode('; ', $responses), - $user - ), $this->baseFormat - ); - $this->doPrivmsg($source, $message); - } - } + $urls[] = $parsed + array('glued' => $this->glueURL($parsed)); } } + + return $urls; } /** @@ -454,52 +451,13 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract */ protected function decode($str, $trim = null) { - $out = $this->decodeTranslit($str); + $out = $this->plugins->encoding->transliterate($str); if ($trim > 0) { $out = substr($out, 0, $trim) . (strlen($out) > $trim ? '...' : ''); } return $out; } - /** - * Custom error handler meant to handle 404 errors and such - * - * @param int $errno the error code - * @param string $errstr the error string - * @param string $errfile file the error occured in - * @param int $errline line the error occured on - * - * @return bool - */ - public function onPhpError($errno, $errstr, $errfile, $errline) - { - if ($errno === E_WARNING) { - // Check to see if there was HTTP warning while connecting to the site - if (preg_match('{HTTP/1\.[01] ([0-9]{3})}i', $errstr, $m)) { - $this->errorStatus = $m[1]; - $this->errorMessage = (isset($this->httpErrors[$m[1]]) ? $this->httpErrors[$m[1]] : $m[1]); - $this->debug('PHP Warning: ' . $errstr . 'in ' . $errfile . ' on line ' . $errline); - return true; - } - - // Safely ignore these SSL warnings so they don't appear in the log - if (stripos($errstr, 'SSL: fatal protocol error in') !== false - || stripos($errstr, 'failed to open stream') !== false - || stripos($errstr, 'HTTP request failed') !== false - || stripos($errstr, 'SSL: An existing connection was forcibly closed by the remote host') !== false - || stripos($errstr, 'Failed to enable crypto in') !== false - || stripos($errstr, 'SSL: An established connection was aborted by the software in your host machine') !== false - || stripos($errstr, 'SSL operation failed with code') !== false - || stripos($errstr, 'unable to connect to') !== false - ) { - $this->errorStatus = true; - $this->debug('PHP Warning: ' . $errstr . 'in ' . $errfile . ' on line ' . $errline); - return true; - } - } - return false; - } - /** * Takes a url, parses and cleans the URL without of all the junk * and then return the hex checksum of the url. @@ -511,7 +469,7 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract protected function getUrlChecksum($url) { $checksum = strtolower(urldecode($this->glueUrl($url, true))); - $checksum = preg_replace('#\s#', '', $this->decodeTranslit($checksum)); + $checksum = preg_replace('#\s#', '', $this->plugins->encoding->transliterate($checksum)); return dechex(crc32($checksum)); } @@ -628,19 +586,20 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract 'user_agent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) Gecko/20080201 Firefox/2.0.0.12' ); - $response = $http->get($url, array(), $options); - + $response = $http->head($url, array(), $options); $header = $response->getHeaders('Content-Type'); + if (!preg_match('#^(text/x?html|application/xhtml+xml)(?:;.*)?$#', $header)) { $title = $header; - } - - $content = $response->getContent(); - if (empty($title)) { + } else { + $response = $http->get($url, array(), $options); + $content = $response->getContent(); if (preg_match('#]*>(.*?)#is', $content, $match)) { - $title = html_entity_decode(trim($match[1])); + $title = preg_replace('/[\s\v]+/', ' ', trim($match[1])); } } + $encoding = $this->plugins->getPlugin('Encoding'); + $title = $encoding->decodeEntities($title); if (empty($title)) { if ($response->isError()) { @@ -665,19 +624,6 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract echo "(DEBUG:Url) $msg\n"; } - /** - * Placeholder/porting helper. Has no function. - * - * @param string $str a string to return - * - * @return string - */ - protected function decodeTranslit($str) - { - // placeholder/porting helper - return $str; - } - /** * Add a renderer to the stack * @@ -687,7 +633,6 @@ class Phergie_Plugin_Url extends Phergie_Plugin_Abstract */ public function registerRenderer($obj) { - $this->renderers[] = $obj; - array_unique($this->renderers); + $this->renderers[spl_object_hash($obj)] = $obj; } } diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Url/url.tld.txt b/plugins/Irc/extlib/phergie/Phergie/Plugin/Url/url.tld.txt deleted file mode 100644 index cc46fdd620..0000000000 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Url/url.tld.txt +++ /dev/null @@ -1,273 +0,0 @@ -ac -ad -ae -aero -af -ag -ai -al -am -an -ao -aq -ar -arpa -as -asia -at -au -aw -ax -az -ba -bb -bd -be -bf -bg -bh -bi -biz -bj -bl -bm -bn -bo -br -bs -bt -bv -bw -by -bz -ca -cat -cc -cd -cf -cg -ch -ci -ck -cl -cm -cn -co -com -coop -cr -cu -cv -cx -cy -cz -de -dj -dk -dm -do -dz -ec -edu -ee -eg -eh -er -es -et -eu -fi -fj -fk -fm -fo -fr -ga -gb -gd -ge -gf -gg -gh -gi -gl -gm -gn -gov -gp -gq -gr -gs -gt -gu -gw -gy -hk -hm -hn -hr -ht -hu -id -ie -il -im -in -info -int -io -iq -ir -is -it -je -jm -jo -jobs -jp -ke -kg -kh -ki -km -kn -kp -kr -kw -ky -kz -la -lb -lc -li -lk -lr -ls -lt -lu -lv -ly -ma -mc -md -me -mf -mg -mh -mil -mk -ml -mm -mn -mo -mobi -mp -mq -mr -ms -mt -mu -museum -mv -mw -mx -my -mz -na -name -nc -ne -net -nf -ng -ni -nl -no -np -nr -nu -nz -om -org -pa -pe -pf -pg -ph -pk -pl -pm -pn -pr -pro -ps -pt -pw -py -qa -re -ro -rs -ru -rw -sa -sb -sc -sd -se -sg -sh -si -sj -sk -sl -sm -sn -so -sr -st -su -sv -sy -sz -tc -td -tel -tf -tg -th -tj -tk -tl -tm -tn -to -tp -tr -travel -tt -tv -tw -tz -ua -ug -uk -um -us -uy -uz -va -vc -ve -vg -vi -vn -vu -wf -ws -ye -yt -yu -za -zm -zw diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Weather.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Weather.php index 499cd9d556..7d4f85a19d 100644 --- a/plugins/Irc/extlib/phergie/Phergie/Plugin/Weather.php +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Weather.php @@ -34,6 +34,7 @@ * @link http://www.weather.com/services/xmloap.html * @uses Phergie_Plugin_Command pear.phergie.org * @uses Phergie_Plugin_Http pear.phergie.org + * @uses Phergie_Plugin_Temperature pear.phergie.org * @uses extension SimpleXML */ class Phergie_Plugin_Weather extends Phergie_Plugin_Abstract @@ -48,6 +49,7 @@ class Phergie_Plugin_Weather extends Phergie_Plugin_Abstract $plugins = $this->getPluginHandler(); $plugins->getPlugin('Command'); $plugins->getPlugin('Http'); + $plugins->getPlugin('Temperature'); if (empty($this->config['weather.partner_id']) || empty($this->config['weather.license_key'])) { @@ -55,30 +57,6 @@ class Phergie_Plugin_Weather extends Phergie_Plugin_Abstract } } - /** - * Converts a temperature in Celsius to Fahrenheit. - * - * @param int $temp Temperature in Celsius - * - * @return int Temperature converted to Fahrenheit - */ - public function convertCelsiusToFahrenheit($temp) - { - return round(((((int) $temp * 9) / 5) + 32)); - } - - /** - * Converts a temperature in Fahrenheit to Celsius. - * - * @param int $temp Temperature in Fahrenheit - * - * @return int Temperature converted to Celsius - */ - public function convertFahrenheitToCelsius($temp) - { - return round(((((int) $temp - 32) * 5) / 9)); - } - /** * Returns a weather report for a specified location. * @@ -129,16 +107,17 @@ class Phergie_Plugin_Weather extends Phergie_Plugin_Abstract return; } + $temperature = $this->plugins->getPlugin('Temperature'); $xml = $response->getContent(); $weather = 'Weather for ' . (string) $xml->loc->dnam . ' - '; switch ($xml->head->ut) { case 'F': $tempF = $xml->cc->tmp; - $tempC = $this->convertFahrenheitToCelsius($tempF); + $tempC = $temperature->convertFahrenheitToCelsius($tempF); break; case 'C': $tempC = $xml->cc->tmp; - $tempF = $this->convertCelsiusToFahrenheit($tempC); + $tempF = $temperature->convertCelsiusToFahrenheit($tempC); break; default: $this->doNotice( @@ -147,20 +126,8 @@ class Phergie_Plugin_Weather extends Phergie_Plugin_Abstract break; } $r = $xml->cc->hmid; - $tempF2 = $tempF * $tempF; - $r2 = $r * $r; - $hiF = round( - -42.379 + - (2.04901523 * $tempF) + - (10.14333127 * $r) - - (.22475541 * $tempF * $r) - - (6.83783 * pow(10,-3) * $tempF2) - - (5.481717 * pow(10,-2) * $r2) + - (1.22874 * pow(10,-3) * $tempF2 * $r) + - (8.5282 * pow(10,-4) * $tempF * $r2) - - (1.99 * pow(10,-6) * $tempF2 * $r2) - ); - $hiC = $this->convertFahrenheitToCelsius($hiF); + $hiF = $temperature->getHeatIndex($tempF, $r); + $hiC = $temperature->convertFahrenheitToCelsius($hiF); $weather .= 'Temperature: ' . $tempF . 'F/' . $tempC . 'C'; $weather .= ', Humidity: ' . (string) $xml->cc->hmid . '%'; if ($hiF > $tempF || $hiC > $tempC) { diff --git a/plugins/Irc/extlib/phergie/Phergie/Plugin/Youtube.php b/plugins/Irc/extlib/phergie/Phergie/Plugin/Youtube.php new file mode 100644 index 0000000000..b19e9d5aef --- /dev/null +++ b/plugins/Irc/extlib/phergie/Phergie/Plugin/Youtube.php @@ -0,0 +1,168 @@ + + * @copyright 2008-2010 Phergie Development Team (http://phergie.org) + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_Youtube + */ + +/** + * Provides commands used to access several services offered by Google + * including search, translation, weather, maps, and currency and general + * value unit conversion. + * + * @category Phergie + * @package Phergie_Plugin_Youtube + * @author Phergie Development Team + * @license http://phergie.org/license New BSD License + * @link http://pear.phergie.org/package/Phergie_Plugin_Youtube + * @uses Phergie_Plugin_Command pear.phergie.org + * @uses Phergie_Plugin_Http pear.phergie.org + */ +class Phergie_Plugin_Youtube extends Phergie_Plugin_Abstract +{ + /** + * Checks for dependencies. + * + * @return void + */ + public function onLoad() + { + $plugins = $this->getPluginHandler(); + $plugins->getPlugin('Command'); + $plugins->getPlugin('Http'); + if ($url = $plugins->getPlugin('Url')) { + $url->registerRenderer($this); + } + } + + /** + * Queries the YouTube video search web service, processes the first + * result, and sends a message back to the current event source. + * + * @param string $query Search term + * + * @return object YouTube result object + */ + protected function queryYoutube($query) + { + $url = 'http://gdata.youtube.com/feeds/api/videos'; + $params = array( + 'max-results' => '1', + 'alt' => 'json', + 'q' => $query + ); + $http = $this->plugins->getPlugin('Http'); + $response = $http->get($url, $params); + $json = $response->getContent(); + + $entries = $json->feed->entry; + if (!$entries) { + $this->doNotice($this->event->getNick(), 'Query returned no results'); + return; + } + $entry = reset($entries); + + $nick = $this->event->getNick(); + $link = $entry->link[0]->href; + $title = $entry->title->{'$t'}; + $author = $entry->author[0]->name->{'$t'}; + $seconds = $entry->{'media$group'}->{'yt$duration'}->seconds; + $published = $entry->published->{'$t'}; + $views = $entry->{'yt$statistics'}->viewCount; + $rating = $entry->{'gd$rating'}->average; + + $minutes = floor($seconds / 60); + $seconds = str_pad($seconds % 60, 2, '0', STR_PAD_LEFT); + $parsed_link = parse_url($link); + parse_str($parsed_link['query'], $parsed_query); + $link = 'http://youtu.be/' . $parsed_query['v']; + $published = date('n/j/y g:i A', strtotime($published)); + $views = number_format($views, 0); + $rating = round($rating, 2); + + $format = $this->getConfig('youtube.format'); + if (!$format) { + $format = '%nick%:' + . ' [ %link% ]' + . ' "%title%" by %author%,' + . ' Length %minutes%:%seconds%,' + . ' Published %published%,' + . ' Views %views%,' + . ' Rating %rating%'; + } + + $replacements = array( + 'nick' => $nick, + 'link' => $link, + 'title' => $title, + 'author' => $author, + 'minutes' => $minutes, + 'seconds' => $seconds, + 'published' => $published, + 'views' => $views, + 'rating' => $rating + ); + + $msg = $format; + foreach ($replacements as $from => $to) { + $msg = str_replace('%' . $from . '%', $to, $msg); + } + $this->doPrivmsg($this->event->getSource(), $msg); + } + + /** + * Returns the first result of a YouTube search. + * + * @param string $query Search query + * + * @return void + */ + public function onCommandYoutube($query) + { + $this->queryYoutube($query); + } + + /** + * Renders YouTube URLs. + * + * @param array $parsed parse_url() output for the URL to render + * + * @return boolean TRUE if the URL was rendered successfully, FALSE + * otherwise + */ + public function renderUrl(array $parsed) + { + switch ($parsed['host']) { + case 'youtu.be': + $v = ltrim('/', $parsed['path']); + break; + case 'youtube.com': + case 'www.youtube.com': + parse_str($parsed['query'], $parsed_query); + if (!empty($parsed_query['v'])) { + $v = $parsed_query['v']; + break; + } + default: + return false; + } + + $this->queryYoutube($v); + + return true; + } +}