You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
4.2 KiB

1 year ago
  1. <?php
  2. /**
  3. * This file is part of the PHP Telegram Bot example-bot package.
  4. * https://github.com/php-telegram-bot/example-bot/
  5. *
  6. * (c) PHP Telegram Bot Team
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. /**
  12. * User "/weather" command
  13. *
  14. * Get weather info for the location passed as the parameter..
  15. *
  16. * A OpenWeatherMap.org API key is required for this command!
  17. * You can be set in your config.php file:
  18. * ['commands']['configs']['weather'] => ['owm_api_key' => 'your_owm_api_key_here']
  19. */
  20. namespace Longman\TelegramBot\Commands\UserCommands;
  21. use Exception;
  22. use GuzzleHttp\Client;
  23. use GuzzleHttp\Exception\RequestException;
  24. use Longman\TelegramBot\Commands\UserCommand;
  25. use Longman\TelegramBot\Entities\ServerResponse;
  26. use Longman\TelegramBot\Exception\TelegramException;
  27. use Longman\TelegramBot\TelegramLog;
  28. class WeatherCommand extends UserCommand
  29. {
  30. /**
  31. * @var string
  32. */
  33. protected $name = 'weather';
  34. /**
  35. * @var string
  36. */
  37. protected $description = 'Show weather by location';
  38. /**
  39. * @var string
  40. */
  41. protected $usage = '/weather <location>';
  42. /**
  43. * @var string
  44. */
  45. protected $version = '1.3.0';
  46. /**
  47. * Base URI for OpenWeatherMap API
  48. *
  49. * @var string
  50. */
  51. private $owm_api_base_uri = 'http://api.openweathermap.org/data/2.5/';
  52. /**
  53. * Get weather data using HTTP request
  54. *
  55. * @param string $location
  56. *
  57. * @return string
  58. */
  59. private function getWeatherData($location): string
  60. {
  61. $client = new Client(['base_uri' => $this->owm_api_base_uri]);
  62. $path = 'weather';
  63. $query = [
  64. 'q' => $location,
  65. 'units' => 'metric',
  66. 'APPID' => trim($this->getConfig('owm_api_key')),
  67. ];
  68. try {
  69. $response = $client->get($path, ['query' => $query]);
  70. } catch (RequestException $e) {
  71. TelegramLog::error($e->getMessage());
  72. return '';
  73. }
  74. return (string) $response->getBody();
  75. }
  76. /**
  77. * Get weather string from weather data
  78. *
  79. * @param array $data
  80. *
  81. * @return string
  82. */
  83. private function getWeatherString(array $data): string
  84. {
  85. try {
  86. if (!(isset($data['cod']) && $data['cod'] === 200)) {
  87. return '';
  88. }
  89. //http://openweathermap.org/weather-conditions
  90. $conditions = [
  91. 'clear' => ' ☀️',
  92. 'clouds' => ' ☁️',
  93. 'rain' => ' ☔',
  94. 'drizzle' => ' ☔',
  95. 'thunderstorm' => ' ⚡️',
  96. 'snow' => ' ❄️',
  97. ];
  98. $conditions_now = strtolower($data['weather'][0]['main']);
  99. return sprintf(
  100. 'The temperature in %s (%s) is %s°C' . PHP_EOL .
  101. 'Current conditions are: %s%s',
  102. $data['name'], //city
  103. $data['sys']['country'], //country
  104. $data['main']['temp'], //temperature
  105. $data['weather'][0]['description'], //description of weather
  106. $conditions[$conditions_now] ?? ''
  107. );
  108. } catch (Exception $e) {
  109. TelegramLog::error($e->getMessage());
  110. return '';
  111. }
  112. }
  113. /**
  114. * Main command execution
  115. *
  116. * @return ServerResponse
  117. * @throws TelegramException
  118. */
  119. public function execute(): ServerResponse
  120. {
  121. // Check to make sure the required OWM API key has been defined.
  122. $owm_api_key = $this->getConfig('owm_api_key');
  123. if (empty($owm_api_key)) {
  124. return $this->replyToChat('OpenWeatherMap API key not defined.');
  125. }
  126. $location = trim($this->getMessage()->getText(true));
  127. if ($location === '') {
  128. return $this->replyToChat('You must specify a location as: ' . $this->getUsage());
  129. }
  130. $text = 'Cannot find weather for location: ' . $location;
  131. if ($weather_data = json_decode($this->getWeatherData($location), true)) {
  132. $text = $this->getWeatherString($weather_data);
  133. }
  134. return $this->replyToChat($text);
  135. }
  136. }