From b666d6cc199c855498f086fab39c16d7272c0c88 Mon Sep 17 00:00:00 2001 From: Don Armstrong Date: Thu, 4 Oct 2012 19:42:27 +0000 Subject: [PATCH] update google weather --- emacs_el/google-weather.el | 44 +++++++++++--- emacs_el/org-google-weather.el | 107 +++++++++++++++++++++------------ 2 files changed, 103 insertions(+), 48 deletions(-) diff --git a/emacs_el/google-weather.el b/emacs_el/google-weather.el index be09e34..4ecf3bc 100644 --- a/emacs_el/google-weather.el +++ b/emacs_el/google-weather.el @@ -38,9 +38,10 @@ "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" @@ -75,7 +76,7 @@ (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 @@ -88,7 +89,18 @@ to 0 force a cache renewal." (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")) @@ -96,11 +108,9 @@ to 0 force a cache renewal." (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." @@ -186,4 +196,20 @@ It uses `google-weather-unit-system-temperature-assoc' to find a 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) diff --git a/emacs_el/org-google-weather.el b/emacs_el/org-google-weather.el index ccb4e46..2acf960 100644 --- a/emacs_el/org-google-weather.el +++ b/emacs_el/org-google-weather.el @@ -41,7 +41,8 @@ (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." @@ -97,50 +98,78 @@ Valid %-sequences are: (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) -- 2.39.5