forecast.lisp 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. (in-package #:chatikbot)
  2. (defvar *forecast-api-key* nil "forecast.io APIKEY")
  3. (defparameter +forecast-api-url+ "https://api.forecast.io/forecast" "forecast.io API endpoint")
  4. (defun forecast (lat lon &key time (currently t) minutely hourly daily alerts)
  5. (yason:parse
  6. (flexi-streams:octets-to-string
  7. (drakma:http-request (format
  8. nil
  9. "~A/~A/~A,~A~@[,~A~]?units=si&exclude=~:[currently,~;~]~:[minutely,~;~]~:[hourly,~;~]~:[daily,~;~]~:[alerts,~;~]flags&lang=ru"
  10. +forecast-api-url+ *forecast-api-key* lat lon time
  11. currently minutely hourly daily alerts))
  12. :external-format :utf8)
  13. :object-as :alist))
  14. (local-time:reread-timezone-repository :timezone-repository "/usr/share/zoneinfo/")
  15. (defvar *forecast-point-formats*
  16. '((:current . (:year "-" (:month 2) "-" (:day 2) " " (:hour 2) ":" (:min 2)))
  17. (:hour . ((:hour 2) ":" (:min 2)))
  18. (:day . (:year "-" (:month 2) "-" (:day 2))))
  19. "local-time:format-timestring formats for different points")
  20. (defvar *forecast-emojis*
  21. '(("clear-day" . "☀")
  22. ("clear-night" . "⭐")
  23. ("rain" . "☔")
  24. ("snow" . "❄")
  25. ("sleet" . "❄☔")
  26. ("wind" . "💨")
  27. ("fog" . "🌁")
  28. ("cloudy" . "☁")
  29. ("partly-cloudy-day" . "⛅")
  30. ("partly-cloudy-night" . "⛅"))
  31. "Weather-to-emoji mapping")
  32. (defun forecast-format-unixtime (unix format tz)
  33. (local-time:format-timestring nil (local-time:unix-to-timestamp unix)
  34. :format format :timezone tz))
  35. (defun forecast-format-point (type point tz)
  36. (format nil "~A -~@[ ~A~]~@[ ~A~]~:[ ~A-~A~;~:* ~A~2*~]°C"
  37. (forecast-format-unixtime (aget "time" point)
  38. (aget type *forecast-point-formats*)
  39. tz)
  40. (aget (aget "icon" point) *forecast-emojis*)
  41. (aget "summary" point)
  42. (aget "temperature" point) (aget "temperatureMin" point) (aget "temperatureMax" point)))
  43. (defun forecast-format-currently (currently &optional (tz local-time:*default-timezone*))
  44. (when currently
  45. (forecast-format-point :current currently tz)))
  46. (defun forecast-format-hourly (hourly &optional (tz local-time:*default-timezone*))
  47. (when hourly
  48. (format nil "~@[~A~]~{~&~A~}"
  49. (aget "summary" hourly)
  50. (mapcar #'(lambda (point) (forecast-format-point :hour point tz))
  51. (subseq (aget "data" hourly) 0 24)))))
  52. (defun forecast-format-daily (daily &optional (tz local-time:*default-timezone*))
  53. (when daily
  54. (format nil "~@[~A~]~{~&~A~}"
  55. (aget "summary" daily)
  56. (mapcar #'(lambda (point) (forecast-format-point :day point tz))
  57. (subseq (aget "data" daily) 0 7)))))
  58. (defun forecast-format (forecast)
  59. (let* ((timezone (local-time:find-timezone-by-location-name
  60. (aget "timezone" forecast))))
  61. (format nil "~@[Сейчас: ~A~]~@[~&Сегодня: ~A~]~@[~&Неделя: ~A~]"
  62. (forecast-format-currently (aget "currently" forecast) timezone)
  63. (forecast-format-hourly (aget "hourly" forecast) timezone)
  64. (forecast-format-daily (aget "daily" forecast) timezone))))