"Google Weather."
:group 'comm)
-(defcustom google-weather-use-https t
+(defcustom google-weather-use-https nil
"Default protocol to use to access the Google Weather API."
- :group 'google-weather)
+ :group 'google-weather
+ :type 'boolean)
(defconst google-weather-url
"www.google.com/ig/api"
(url-cache-extract (url-cache-create-filename url))
(current-buffer)))
-(defun google-weather-retrieve-data (url &optional expire-time)
+(defun google-weather-retrieve-data-raw (url &optional expire-time)
"Retrieve URL and return its data as string.
If EXPIRE-TIME is set, the data will be fetched from the cache if
their are not older than EXPIRE-TIME seconds. Otherwise, they
(url-retrieve-synchronously url)
(google-weather-cache-fetch url)))
data)
- (with-current-buffer buffer
+ (when (and expired expire-time)
+ (url-store-in-cache buffer))
+ buffer))
+
+(defun google-weather-retrieve-data (url &optional expire-time)
+ "Retrieve URL and return its data as string.
+If EXPIRE-TIME is set, the data will be fetched from the cache if
+their are not older than EXPIRE-TIME seconds. Otherwise, they
+will be fetched and then cached. Therefore, setting EXPIRE-TIME
+to 0 force a cache renewal."
+ (with-current-buffer (google-weather-retrieve-data-raw
+ url expire-time)
(goto-char (point-min))
(unless (search-forward "\n\n" nil t)
(error "Data not found"))
(point) (point-max)
(detect-coding-region (point) (point-max) t))
(set-buffer-multibyte t)
- (setq data (xml-parse-region (point) (point-max)))
- (when (and expired expire-time)
- (url-store-in-cache (current-buffer)))
- (kill-buffer (current-buffer))
- data)))
+ (let ((data (xml-parse-region (point) (point-max))))
+ (kill-buffer (current-buffer))
+ data)))
(defun google-weather-build-url (location &optional language)
"Build URL to retrieve weather for LOCATION in LANGUAGE."
match."
(cdr (assoc (google-weather-data->unit-system data) google-weather-unit-system-temperature-assoc)))
+
+(defun google-weather-data->problem-cause (data)
+ "Return a string if DATA contains a problem cause, `nil' otherwise.
+
+An error message example:
+
+((xml_api_reply
+ ((version . \"1\"))
+ (weather
+ ((module_id . \"0\") (tab_id . \"0\") (mobile_row . \"0\")
+ (mobile_zipped . \"1\") (row . \"0\") (section . \"0\"))
+ (problem_cause ((data . \"Information is temporarily unavailable.\"))))))))"
+ (google-weather-assoc
+ 'problem_cause
+ (google-weather-data->weather data)))
+
(provide 'google-weather)
(defgroup org-google-weather nil
"Google Weather for Org mode."
- :group 'comm)
+ :group 'comm
+ :group 'org)
(defcustom org-google-weather-location calendar-location-name
"Default location for org-google-weather."
(storm . "weather-storm.png")
(thunderstorm . "weather-storm.png")
(sunny . "weather-clear.png"))
- "Icons to use to illustrate the weather.")
+ "Icons to use to illustrate the weather."
+ :group 'org-google-weather)
+
+(defcustom org-google-weather-use-google-icons nil
+ "Fetch icons from Google or use local ones.
+If you decide to use local ones, you should check
+`org-google-weather-icon-directory' and
+`org-google-weather-icon-alist'. Otherwise, if you want to use
+icons from Google, you have nothing to do."
+ :group 'org-google-weather
+ :type 'boolean)
+
+(defun org-google-weather-get-icon (url)
+ (with-current-buffer
+ (google-weather-retrieve-data-raw url org-google-weather-cache-time)
+ (goto-char (point-min))
+ (unless (search-forward "\n\n" nil t)
+ (error "Data not found"))
+ (let ((data (buffer-substring (point) (point-max))))
+ (kill-buffer (current-buffer))
+ data)))
;;;###autoload
(defun org-google-weather (&optional location language)
"Return Org entry with the weather for LOCATION in LANGUAGE.
If LOCATION is not set, use org-google-weather-location."
- (let* ((data (ignore-errors
- (google-weather-get-data (or location
- org-google-weather-location)
+ (let* ((location (or location org-google-weather-location))
+ (data (ignore-errors
+ (google-weather-get-data location
language
org-google-weather-cache-time)))
- (forecast (when data (google-weather-data->forecast-for-date data date))))
- (when forecast
- (let ((condition (cadr (assoc 'condition forecast)))
- (low (cadr (assoc 'low forecast)))
- (high (cadr (assoc 'high forecast)))
- (city (google-weather-data->city data))
- ;; But *they* told me it's just about calling functions!
- (icon (when window-system
- (cdr
- (assoc
- (intern
- (file-name-sans-extension
- (file-name-nondirectory
- (cadr (assoc 'icon forecast)))))
- org-google-weather-icon-alist))))
- (temp-symbol (google-weather-data->temperature-symbol data)))
- (format-spec org-google-weather-format
- `((?i . ,(if (and icon org-google-weather-display-icon-p)
- (propertize "icon"
- 'display
- (append
- (create-image
- (concat
- org-google-weather-icon-directory
- "/"
- icon)) '(:ascent center))
- 'rear-nonsticky '(display))
- ""))
- (?c . ,condition)
- (?L . ,location)
- (?C . ,city)
- (?l . ,low)
- (?h . ,high)
- (?s . ,temp-symbol)))))))
+ (problem-cause (when data (google-weather-data->problem-cause data)))
+ (forecast (when (and (null problem-cause) data)
+ (google-weather-data->forecast-for-date data date))))
+ (if problem-cause
+ (message "%s: %s" location problem-cause)
+ (when forecast
+ (let ((condition (cadr (assoc 'condition forecast)))
+ (low (cadr (assoc 'low forecast)))
+ (high (cadr (assoc 'high forecast)))
+ (city (google-weather-data->city data))
+ ;; But *they* told me it's just about calling functions!
+ (icon (when (and org-google-weather-display-icon-p (display-images-p))
+ (if org-google-weather-use-google-icons
+ (create-image (org-google-weather-get-icon
+ (cadr (assoc 'icon forecast)))
+ nil t)
+ (create-image
+ (concat
+ org-google-weather-icon-directory
+ "/"
+ (cdr
+ (assoc
+ (intern
+ (file-name-sans-extension
+ (file-name-nondirectory
+ (cadr (assoc 'icon forecast)))))
+ org-google-weather-icon-alist)))))))
+ (temp-symbol (google-weather-data->temperature-symbol data)))
+ (format-spec org-google-weather-format
+ `((?i . ,(if icon
+ (propertize "icon"
+ 'display
+ (append
+ icon '(:ascent center))
+ 'rear-nonsticky '(display))
+ ""))
+ (?c . ,condition)
+ (?L . ,location)
+ (?C . ,city)
+ (?l . ,low)
+ (?h . ,high)
+ (?s . ,temp-symbol))))))))
(provide 'org-google-weather)