meteo

meteo.inc

  1. <?php
  2. // vim:filetype=php expandtab tabstop=2 softtabstop=2 shiftwidth=2 autoindent smartindent
  3. // $Id$
  4.  
  5. function tribune_meteo_info() {
  6.   return t('Gives weather information.');
  7. }
  8.  
  9. function tribune_meteo_filter(&$post) {
  10.   $answer = array(
  11.     'info' => variable_get('tribune_meteo_name', "Meteo"),
  12.   );
  13.  
  14.   if (variable_get('tribune_meteo_authentified', FALSE)) {
  15.     $answer['login'] = $answer['info'];
  16.   }
  17.  
  18.   if (preg_match(':^/'. t('weather') .' (.+)$:', $post['message'], $matches)) {
  19.     $city = $matches[1];
  20.     $answer['message'] = _tribune_meteo_get_weather_info($city);
  21.     $answer['message'] = tribune_filters_print_clock($post) ." ". $answer['message'];
  22.     return array($answer);
  23.   }
  24.   elseif (preg_match(':^/'. t('forecast') .'? (.+)$:', $post['message'], $matches)) {
  25.     $city = $matches[1];
  26.     $answer['message'] = _tribune_meteo_get_weather_forecast($city);
  27.     $answer['message'] = tribune_filters_print_clock($post) ." ". $answer['message'];
  28.     return array($answer);
  29.   }
  30. }
  31.  
  32. function tribune_meteo_help() {
  33.   $user = array_shift(user_load_self(array()));
  34.   $help = 'Type "/weather <em>city</em>" for weather information, "/forecast <em>city</em>" for a forecast.';
  35.   return $help;
  36. }
  37.  
  38. function _tribune_meteo_get_weather_info($city) {
  39.   if (preg_match("/[A-Z]{4}[0-9]{4}/", $city)) {
  40.     return _tribune_meteo_get_yahoo_weather_info(strtoupper($city));
  41.   }
  42.   else {
  43.     return _tribune_meteo_get_google_weather_info($city);
  44.   }
  45. }
  46.  
  47. function _tribune_meteo_get_weather_forecast($city) {
  48.   if (preg_match("/[A-Z]{4}[0-9]{4}/", $city)) {
  49.     return _tribune_meteo_get_yahoo_weather_forecast(strtoupper($city));
  50.   }
  51.   else {
  52.     return _tribune_meteo_get_google_weather_forecast($city);
  53.   }
  54. }
  55.  
  56. function _tribune_meteo_get_google_feed($city) {
  57.   $lang = $language['language'];
  58.   $units = variable_get('tribune_meteo_imperial', FALSE) ? 'US' : 'SI';
  59.   $url = "http://www.google.co.uk/ig/api?hl=". $lang ."&weather=". urlencode($city);
  60.  
  61.   $ch = curl_init();
  62.   curl_setopt($ch, CURLOPT_URL, $url);
  63.   curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  64.   $result = curl_exec($ch);
  65.   try {
  66.     $xml = new SimpleXMLElement(utf8_encode($result), LIBXML_NOERROR | LIBXML_NOWARNING);
  67.  
  68.     if ($xml->xpath("/xml_api_reply/weather/problem_cause")) {
  69.       return array('error' => t("Unable to find weather data for <i>@city</i>", array('@city' => $city)));
  70.     }
  71.  
  72.     return array('error' => FALSE, 'xml' => $xml, 'lang' => $lang, 'units' => $units);
  73.   }
  74.   catch (Exception $e) {
  75.     return array('error' => $e->getMessage());
  76.   }
  77. }
  78.  
  79. function _tribune_meteo_get_google_weather_info($city) {
  80.   $result = _tribune_meteo_get_google_feed($city);
  81.  
  82.   if ($result['error']) {
  83.     $info = $result['error'];
  84.   }
  85.   else {
  86.     $xml = $result['xml'];
  87.     $to_units = strtolower($result['units']);
  88.     $node = $xml->xpath("/xml_api_reply/weather/forecast_information/unit_system");
  89.     $unit_system = $node[0]['data'];
  90.     switch ($to_units) {
  91.       case "us":
  92.         $temp_unit = "F";
  93.         $speed_unit = "mph";
  94.         break;
  95.       default:
  96.         $to_units = "si";
  97.       case "si":
  98.         $temp_unit = "C";
  99.         $speed_unit = "km/h";
  100.         break;
  101.     }
  102.  
  103.     $node = $xml->xpath("/xml_api_reply/weather/forecast_information/city");
  104.     $city = $node[0]['data'];
  105.  
  106.     $node = $xml->xpath("/xml_api_reply/weather/current_conditions/wind_condition");
  107.     $wind = $node[0]['data'];
  108.  
  109.     if ($to_units == "us") {
  110.       $node = $xml->xpath("/xml_api_reply/weather/current_conditions/temp_f");
  111.     }
  112.     else {
  113.       $node = $xml->xpath("/xml_api_reply/weather/current_conditions/temp_c");
  114.     }
  115.     $temp = $node[0]['data'];
  116.  
  117.     $node = $xml->xpath("/xml_api_reply/weather/current_conditions/condition");
  118.     $desc = $node[0]['data'];
  119.  
  120.     $node = $xml->xpath("/xml_api_reply/weather/current_conditions/humidity");
  121.     $humidity = preg_replace('/^[^0-9]*([0-9]*)%[^0-9]*$/', '$1', $node[0]['data']);
  122.  
  123.  
  124.     $info = t("Weather in <b>@city</b>: @desc, @temp °@temp_unit, humidity: @humidity%",
  125.       array('@city' => $city,
  126.             '@desc' => $desc,
  127.             '@temp' => $temp,
  128.             '@temp_unit' => $temp_unit,
  129.             '@humidity' => $humidity));
  130.   }
  131.  
  132.   return $info;
  133. }
  134.  
  135. function _tribune_meteo_get_google_weather_forecast($city) {
  136.   $result = _tribune_meteo_get_google_feed($city);
  137.  
  138.   if ($result['error']) {
  139.     return $result['error'];
  140.   }
  141.   else {
  142.     $xml = $result['xml'];
  143.     $to_units = strtolower($result['units']);
  144.     $node = $xml->xpath("/xml_api_reply/weather/forecast_information/unit_system");
  145.     $unit_system = strtolower($node[0]['data']);
  146.     switch ($to_units) {
  147.       case "us":
  148.         $temp_unit = "F";
  149.         $speed_unit = "mph";
  150.         break;
  151.       default:
  152.         $to_units = "si";
  153.       case "si":
  154.         $temp_unit = "C";
  155.         $speed_unit = "km/h";
  156.         break;
  157.     }
  158.  
  159.     $node = $xml->xpath("/xml_api_reply/weather/forecast_information/city");
  160.     $city = $node[0]['data'];
  161.  
  162.     $conditions = array();
  163.     $node = $xml->xpath("/xml_api_reply/weather/forecast_conditions");
  164.     foreach ($node as $forecast) {
  165.       $date = "";
  166.       $high = "?";
  167.       $low  = "?";
  168.       $desc = "?";
  169.       foreach ($forecast->children() as $child) {
  170.         $value = $child['data'];
  171.         switch ($child->getName()) {
  172.           case 'high':
  173.             $high = tribune_meteo_temp($value, $unit_system, $to_units);
  174.             break;
  175.           case 'low':
  176.             $low = tribune_meteo_temp($value, $unit_system, $to_units);
  177.             break;
  178.           case 'day_of_week':
  179.             $date = $value;
  180.             break;
  181.           case 'condition':
  182.             $desc = $value;
  183.             break;
  184.         }
  185.       }
  186.  
  187.       if ($date) {
  188.         $conditions[] = array(
  189.           'date' => $date,
  190.           'high' => $high,
  191.           'low'  => $low,
  192.           'desc' => $desc,
  193.         );
  194.       }
  195.     }
  196.     $args = array();
  197.     $info = "Forecast for <b>@city</b> ― ";
  198.     $args['@city'] = $city;
  199.     $args['@temp_unit'] = $temp_unit;
  200.  
  201.     foreach ($conditions as $id => $cond) {
  202.       $info .= "@date". $id .": @low". $id ."»@high". $id ." °@temp_unit (@cond". $id ."), ";
  203.       $args["@date". $id] = $cond['date'];
  204.       $args["@low".  $id] = $cond['low'];
  205.       $args["@high". $id] = $cond['high'];
  206.       $args["@cond". $id] = $cond['desc'];
  207.     }
  208.  
  209.     return t(substr($info, 0, -2), $args);
  210.   }
  211. }
  212.  
  213. function _tribune_meteo_get_yahoo_weather_info($city) {
  214.   $info = "";
  215.  
  216.   $url = "http://weather.yahooapis.com/forecastrss?u=c&p=". $city;
  217.  
  218.   $ch = curl_init();
  219.   curl_setopt($ch, CURLOPT_URL, $url);
  220.   curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  221.   $result = curl_exec($ch);
  222.   $xml = new SimpleXMLElement($result);
  223.  
  224.   $speed_unit = "";
  225.   $temp_unit = "";
  226.   $node = $xml->xpath("/rss/channel/yweather:units");
  227.   foreach ($node[0]->attributes() as $attr => $value) {
  228.     switch ($attr) {
  229.       case 'temperature':
  230.         $temp_unit = $value;
  231.         break;
  232.       case 'speed':
  233.         $speed_unit = $value;
  234.         break;
  235.     }
  236.   }
  237.  
  238.   $city = "?";
  239.   $node = $xml->xpath("/rss/channel/yweather:location");
  240.   foreach ($node[0]->attributes() as $attr => $value) {
  241.     switch ($attr) {
  242.       case 'city':
  243.         $city = $value;
  244.         break;
  245.     }
  246.   }
  247.  
  248.   $wind = "?";
  249.   $node = $xml->xpath("/rss/channel/yweather:wind");
  250.   foreach ($node[0]->attributes() as $attr => $value) {
  251.     switch ($attr) {
  252.       case 'speed':
  253.         $wind = $value;
  254.         break;
  255.     }
  256.   }
  257.  
  258.   $temp = "?";
  259.   $desc = "?";
  260.   $node = $xml->xpath("/rss/channel/item/yweather:condition");
  261.   foreach ($node[0]->attributes() as $attr => $value) {
  262.     switch ($attr) {
  263.       case 'temp':
  264.         $temp = $value;
  265.         break;
  266.       case 'text':
  267.         $desc = $value;
  268.         break;
  269.     }
  270.   }
  271.  
  272.   $info = t("Weather in <b>@city</b>: @desc, @temp °@temp_unit",
  273.     array('@city' => $city,
  274.           '@desc' => $desc,
  275.           '@temp' => $temp,
  276.           '@temp_unit' => $temp_unit));
  277.  
  278.   return $info;
  279. }
  280.  
  281. function _tribune_meteo_get_yahoo_weather_forecast($city) {
  282.   $info = "";
  283.  
  284.   $url = "http://weather.yahooapis.com/forecastrss?u=c&p=". urlencode($city);
  285.  
  286.   $ch = curl_init();
  287.   curl_setopt($ch, CURLOPT_URL, $url);
  288.   curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  289.   $result = curl_exec($ch);
  290.   $xml = new SimpleXMLElement($result);
  291.  
  292.   $speed_unit = "";
  293.   $temp_unit = "";
  294.   $node = $xml->xpath("/rss/channel/yweather:units");
  295.   foreach ($node[0]->attributes() as $attr => $value) {
  296.     switch ($attr) {
  297.       case 'temperature':
  298.         $temp_unit = $value;
  299.         break;
  300.       case 'speed':
  301.         $speed_unit = $value;
  302.         break;
  303.     }
  304.   }
  305.  
  306.   $city = "?";
  307.   $node = $xml->xpath("/rss/channel/yweather:location");
  308.   foreach ($node[0]->attributes() as $attr => $value) {
  309.     switch ($attr) {
  310.       case 'city':
  311.         $city = $value;
  312.         break;
  313.     }
  314.   }
  315.  
  316.   $conditions = array();
  317.   $node = $xml->xpath("/rss/channel/item/yweather:forecast");
  318.   foreach ($node as $forecast) {
  319.     $date = "";
  320.     $high = "?";
  321.     $low  = "?";
  322.     $desc = "?";
  323.     foreach ($forecast->attributes() as $attr => $value) {
  324.       switch ($attr) {
  325.         case 'high':
  326.           $high = $value;
  327.           break;
  328.         case 'low':
  329.           $low = $value;
  330.           break;
  331.         case 'date':
  332.           $date = $value;
  333.           break;
  334.         case 'text':
  335.           $desc = $value;
  336.           break;
  337.       }
  338.     }
  339.  
  340.     if ($date) {
  341.       $timestamp = strtotime($date);
  342.       $conditions[$timestamp] = array(
  343.         'date' => date('d/m/Y', $timestamp),
  344.         'high' => $high,
  345.         'low'  => $low,
  346.         'desc' => $desc,
  347.       );
  348.     }
  349.   }
  350.  
  351.   $args = array();
  352.   $info = "Forecast for <b>@city</b> ― ";
  353.   $args['@city'] = $city;
  354.   $args['@temp_unit'] = $temp_unit;
  355.  
  356.   foreach ($conditions as $timestamp => $cond) {
  357.     $info .= "@date$timestamp: @low${timestamp}»@high$timestamp °@temp_unit, ";
  358.     $args["@date". $timestamp] = $cond['date'];
  359.     $args["@low".  $timestamp] = $cond['low'];
  360.     $args["@high". $timestamp] = $cond['high'];
  361.   }
  362.  
  363.   return t(substr($info, 0, -2), $args);
  364. }
  365.  
  366. function tribune_meteo_f2c($fahrenheit) {
  367.   return round(($fahrenheit-32)*(5/9));
  368. }
  369.  
  370. function tribune_meteo_c2f($celsius) {
  371.   return round($celsius*(5/9)+32);
  372. }
  373.  
  374. function tribune_meteo_temp($value, $from, $to) {
  375.   $from = strtolower($from);
  376.   $to   = strtolower($to);
  377.  
  378.   if ($from != $to) {
  379.     switch ($to) {
  380.       case 'si':
  381.         return tribune_meteo_f2c($value);
  382.       case 'us':
  383.         return tribune_meteo_c2f($value);
  384.       default:
  385.         return $value;
  386.     }
  387.   }
  388.   else {
  389.     return $value;
  390.   }
  391. }
  392.  
  393. function tribune_meteo_settings() {
  394.   $form = array();
  395.  
  396.   $form['tribune_meteo_name'] = array(
  397.     '#type'           => "textfield",
  398.     '#title'          => t("Display name"),
  399.     '#default_value'  => variable_get('tribune_meteo_name', "Meteo"),
  400.   );
  401.  
  402.   $form['tribune_meteo_authentified'] = array(
  403.     '#type'           => "checkbox",
  404.     '#title'          => t("Appear to be authentified"),
  405.     '#default_value'  => variable_get('tribune_meteo_authentified', FALSE),
  406.     '#description'    => t("Whether this filter will appear to be 'anonymous' or 'authentified'. Since the filter does not correspond to a real user, posting as authentified may result in 'nickname collisions'."),
  407.   );
  408.  
  409.   $form['tribune_meteo_imperial'] = array(
  410.     '#type'           => "checkbox",
  411.     '#title'          => t("Use imperial system"),
  412.     '#default_value'  => variable_get('tribune_meteo_imperial', FALSE),
  413.     '#description'    => t("If this is enabled, the imperial system will be used, otherwise SI units will be shown."),
  414.   );
  415.  
  416.   return system_settings_form($form);
  417. }
  418.