changelog shortlog tags changeset files revisions annotate raw

google-weather.el

changeset 66: 5b737eefe5ea
author: kim.vanwyk
date: Wed Nov 10 15:19:03 2010 +0200 (18 months ago)
permissions: -rw-r--r--
description: Adding CSharp Mode and Google Weather
1;;; google-weather.el --- Fetch Google Weather forecasts.
2
3;; Copyright (C) 2010 Julien Danjou
4
5;; Author: Julien Danjou <julien@danjou.info>
6;; Keywords: comm
7
8;; This file is NOT part of GNU Emacs.
9
10;; GNU Emacs is free software: you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
21;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
22
23;;; Commentary:
24;; This module allows you to fetch Google Weather forecast from the
25;; Internet.
26;;
27;;; Code:
28
29(require 'url)
30(require 'url-cache)
31(require 'xml)
32(require 'time-date)
33
34(eval-when-compile
35 (require 'cl))
36
37(defgroup google-weather nil
38 "Google Weather."
39 :group 'comm)
40
41(defconst google-weather-url
42 "http://www.google.com/ig/api"
43 "URL of the Google Weather API.")
44
45(defconst google-weather-image-url
46 "http://www.google.com"
47 "URL prefix for images.")
48
49(defcustom google-weather-unit-system-temperature-assoc
50 '(("SI" . "℃")
51 ("US" . "℉"))
52 "Find temperature symbol from unit system."
53 :group 'google-weather)
54
55(defun google-weather-cache-expired (url expire-time)
56 "Check if URL is cached for more than EXPIRE-TIME."
57 (cond (url-standalone-mode
58 (not (file-exists-p (url-cache-create-filename url))))
59 (t (let ((cache-time (url-is-cached url)))
60 (if cache-time
61 (time-less-p
62 (time-add
63 cache-time
64 (seconds-to-time expire-time))
65 (current-time))
66 t)))))
67
68(defun google-weather-cache-fetch (url)
69 "Fetch URL from the cache."
70 (with-current-buffer (generate-new-buffer " *temp*")
71 (url-cache-extract (url-cache-create-filename url))
72 (current-buffer)))
73
74(defun google-weather-retrieve-data (url &optional expire-time)
75 "Retrieve URL and return its data as string.
76If EXPIRE-TIME is set, the data will be fetched from the cache if
77their are not older than EXPIRE-TIME seconds. Otherwise, they
78will be fetched and then cached. Therefore, setting EXPIRE-TIME
79to 0 force a cache renewal."
80 (let* ((expired (if expire-time
81 (google-weather-cache-expired url expire-time)
82 t))
83 (buffer (if expired
84 (url-retrieve-synchronously url)
85 (google-weather-cache-fetch url)))
86 data)
87 (with-current-buffer buffer
88 (goto-char (point-min))
89 (search-forward "\n\n")
90 (decode-coding-region
91 (point) (point-max)
92 (detect-coding-region (point) (point-max) t))
93 (set-buffer-multibyte t)
94 (setq data (xml-parse-region (point) (point-max)))
95 (when (and expired expire-time)
96 (url-store-in-cache (current-buffer)))
97 (kill-buffer (current-buffer))
98 data)))
99
100(defun google-weather-build-url (location &optional language)
101 "Build URL to retrieve weather for LOCATION in LANGUAGE."
102 (concat google-weather-url "?weather=" (url-hexify-string location)
103 (when language
104 (concat "&hl=" language))))
105
106(defun google-weather-get-data (location &optional language expire-time)
107 "Get weather data for LOCATION in LANGUAGE.
108See `google-weather-retrieve-data' for the use of EXPIRE-TIME."
109 (google-weather-retrieve-data
110 (google-weather-build-url location language) expire-time))
111
112(defun google-weather-data->weather (data)
113 "Return all weather information from DATA."
114 (cddr (assoc 'weather (cdr (assoc 'xml_api_reply data)))))
115
116(defun google-weather-data->forecast-information (data)
117 "Return the forecast information of DATA."
118 (cddr (assoc 'forecast_information (google-weather-data->weather data))))
119
120(defun google-weather-assoc (key data)
121 "Extract value of field KEY from DATA."
122 (cdr (assoc 'data (cadr (assoc key data)))))
123
124(defun google-weather-data->city (data)
125 "Return the city where the DATA come from."
126 (google-weather-assoc
127 'city
128 (google-weather-data->forecast-information data)))
129
130(defun google-weather-data->postal-code (data)
131 "Return the postal code where the DATA come from."
132 (google-weather-assoc
133 'postal_code
134 (google-weather-data->forecast-information data)))
135
136(defun google-weather-data->unit-system (data)
137 "Return the unit system used for DATA."
138 (google-weather-assoc
139 'unit_system
140 (google-weather-data->forecast-information data)))
141
142(defun google-weather-data->forecast-date (data)
143 "Return the unit system used for DATA."
144 (google-weather-assoc
145 'forecast_date
146 (google-weather-data->forecast-information data)))
147
148(defun google-weather-data->forecast (data)
149 "Get forecast list from DATA."
150 ;; Compute date of the forecast in the same format as `current-time'
151 (let ((date (apply 'encode-time
152 (parse-time-string
153 (concat (google-weather-data->forecast-date data) " 00:00:00")))))
154 (mapcar
155 (lambda (forecast)
156 (let* ((forecast-date (decode-time date))
157 (forecast-encoded-date (list (nth 4 forecast-date)
158 (nth 3 forecast-date)
159 (nth 5 forecast-date))))
160 ;; Add one day to `date'
161 (setq date (time-add date (days-to-time 1)))
162 `(,forecast-encoded-date
163 (low ,(google-weather-assoc 'low forecast))
164 (high ,(google-weather-assoc 'high forecast))
165 (icon ,(concat google-weather-image-url
166 (google-weather-assoc 'icon forecast)))
167 (condition ,(google-weather-assoc 'condition forecast)))))
168 (loop for entry in (google-weather-data->weather data)
169 when (eq (car entry) 'forecast_conditions)
170 collect entry))))
171
172(defun google-weather-data->forecast-for-date (data date)
173 "Return forecast for DATE from DATA.
174DATE should be in the same format used by calendar,
175i.e. (MONTH DAY YEAR)."
176 (cdr (assoc date (google-weather-data->forecast data))))
177
178(defun google-weather-data->temperature-symbol (data)
179 "Return the temperature to be used according in DATA.
180It uses `google-weather-unit-system-temperature-assoc' to find a
181match."
182 (cdr (assoc (google-weather-data->unit-system data) google-weather-unit-system-temperature-assoc)))
183
184(provide 'google-weather)