;;; emacspeak-url-template.el --- Create library of URI templates
;;; $Id: emacspeak-url-template.el 8272 2013-03-29 15:39:21Z tv.raman.tv $
;;; $Author: tv.raman.tv $
;;; Description:   Implement library of URI templates
;;; Keywords: Emacspeak, Audio Desktop
;;{{{  LCD Archive entry:

;;; LCD Archive Entry:
;;; emacspeak| T. V. Raman |raman@cs.cornell.edu
;;; A speech interface to Emacs |
;;; $Date: 2008-08-14 11:23:31 -0700 (Thu, 14 Aug 2008) $ |
;;;  $Revision: 4626 $ |
;;; Location undetermined
;;;

;;}}}
;;{{{  Copyright:

;;; Copyright (C) 1995 -- 2011, T. V. Raman<raman@cs.cornell.edu>
;;; All Rights Reserved.
;;;
;;; This file is not part of GNU Emacs, but the same permissions apply.
;;;
;;; GNU Emacs is free software; you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 2, or (at your option)
;;; any later version.
;;;
;;; GNU Emacs is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Emacs; see the file COPYING.  If not, write to
;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.

;;}}}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;{{{  Introduction:

;;; Commentary:

;;; It is often useful to have ``parametrized hot list entries''
;;; i.e., hotlist entries  that are ``templates'' for the
;;; actual URL.
;;; The user provides values for the parametrized portions
;;; of the URL e.g. the date.
;;; See @xref{URL Templates}, for details on the URL templates
;;; that are presently defined.

;;; Code:

;;}}}
;;{{{ required modules

(require 'emacspeak-preamble)
(require 'emacspeak-webutils)
(require 'gweb)
(require 'emacspeak-we)
(require 'emacspeak-xslt)
(eval-when-compile
  (require 'calendar))
;;}}}
;;{{{  structures

(defstruct (emacspeak-url-template
            (:constructor emacspeak-url-template-constructor))
  name                                ;Human-readable name
  template                            ;template URL string
  generators                          ; list of param generator
  post-action                         ;action to perform after opening
  documentation                       ;resource  documentation
  fetcher                             ; custom fetcher
  dont-url-encode)

;;}}}
;;{{{ Helpers

(defun emacspeak-url-template-url (ut)
  "Instantiate URL identified by URL template."
  (declare (special emacspeak-url-template-current-ut))
  (setq emacspeak-url-template-current-ut nil)
  (let ((url 
         (apply 'format
                ( emacspeak-url-template-template ut)
                (mapcar
                 #'(lambda (g)
                     (let ((input nil))
                       (setq input
                             (cond
                              ((stringp g)
                               (if (emacspeak-url-template-dont-url-encode ut)
                                   (read-from-minibuffer g)
                                 (emacspeak-url-encode (read-from-minibuffer g))))
                              (t (funcall g))))
                       input))
                 (emacspeak-url-template-generators ut)))))
    (setq emacspeak-url-template-current-ut
          (list (emacspeak-url-template-name ut)))
    url))

(defun emacspeak-url-template-collect-date (prompt time-format-string)
  "Smart date collector.
Prompts with `prompt'.
`time-format-string' is format argument for format-time-string.
This function is sensitive to calendar mode when prompting."
  (let ((default (format-time-string time-format-string))) ; today is default
    (when (eq major-mode 'calendar-mode)
                                        ;get smart default from calendar
      (let ((date (calendar-cursor-to-nearest-date)))
        (setq default (format-time-string time-format-string
                                          (apply 'encode-time 0 0
                                                 0
                                                 (second date)
                                                 (first date)
                                                 (list (third date )))))))
    (read-from-minibuffer prompt
                          default
                          nil nil nil
                          default)))

;;}}}
;;{{{  persistent store

(defvar emacspeak-url-template-table (make-hash-table :test 'equal)
  "Stores URL templates. ")
(defun emacspeak-url-template-set (key ut)
  "Add  specified template to key. "
  (declare (special emacspeak-url-template-table))
  (setf (gethash key emacspeak-url-template-table ) ut))
;;;###autoload
(defun emacspeak-url-template-get (key)
  "Lookup key and return corresponding template. "
  (declare (special emacspeak-url-template-table))
  (gethash key emacspeak-url-template-table))

;;}}}
;;{{{  define resources

;;;###autoload
(defun emacspeak-url-template-define (name template
                                           &optional generators post-action
                                           documentation fetcher
                                           dont-url-encode)
  "Define a URL template.

name            Name used to identify template
template        Template URI with `%s' for slots
generators      List of prompters.
                Generators are strings or functions.
                String values specify prompts.
                Function values are called to obtain values.
post-action     Function called to apply post actions.
                Possible actions include speaking the result.
fetcher         Unless specified, browse-url retrieves URL.
                If specified, fetcher is a function of one arg
                that is called with the URI to retrieve.
documentation   Documents this template resource.
dont-url-encode if true then url arguments are not url-encoded "
  (declare (special emacspeak-url-template-table))
  (emacspeak-url-template-set
   name
   (emacspeak-url-template-constructor
    :name name
    :template template
    :generators generators
    :post-action  post-action
    :documentation documentation
    :fetcher fetcher
    :dont-url-encode dont-url-encode)))

;;;###autoload
(defun emacspeak-url-template-load (file)
  "Load URL template resources from specified location."
  (interactive
   (list
    (read-file-name "Load URL templates from file: "
                    emacspeak-resource-directory)))
  (condition-case nil
      (progn
        (load
         (expand-file-name  file emacspeak-resource-directory)))
    (error (message "Error loading resources from %s "
                    file))))

(defun emacspeak-url-template-save (file)
  "Save out url templates."
  (interactive
   (list
    (read-file-name "Save URL templates to file: "
                    emacspeak-resource-directory)))
  (declare (special emacspeak-resource-directory))
  (let ((buffer (find-file-noselect
                 (expand-file-name file
                                   emacspeak-resource-directory))))
    (save-excursion
      (set-buffer buffer)
      (setq buffer-undo-list t)
      (erase-buffer)
      (loop for key being the hash-keys of
            emacspeak-url-template-table
            do
            (insert
             (format
              "\n(setf
 (gethash %s emacspeak-url-template-table)\n %s)"
              (prin1-to-string key)
              (prin1-to-string (emacspeak-url-template-get key)))))
      (basic-save-buffer)
      (kill-buffer buffer))))

;;}}}
;;{{{  template resources
;;{{{ twitter:

(emacspeak-url-template-define
 "Twitter Search"
 "http://search.twitter.com/search.atom?q=%s"
 (list "Twitter Search: ")
 nil
 "Twitter search and display results feed."
 'emacspeak-webutils-atom-display)

;;}}}
;;{{{  powerset

(emacspeak-url-template-define
 "PowerSet Wikipedia Search"
 "http://www.powerset.com/explore/pset?q=%s"
 (list "PowerSet: ")
 nil
 "Perform powerset query.")

;;}}}
;;{{{ Mozilla MDC

(emacspeak-url-template-define
 "Mozilla Developers Corner"
 "http://developer.mozilla.org/en/docs/%s"
 (list "MDC: ")
 nil
 "Pull specified resource from MDC.")

(emacspeak-url-template-define
 "MDC Search"
 "http://developer.mozilla.org/en/docs/Special:Nutch?language=en&start=0&hitsPerPage=10&query=%s&fulltext=Search"
 (list "MDC: ")
 nil
 "Search MDC Wiki."
 #'(lambda (url)
     (emacspeak-we-extract-by-id "content" url 'speak)))

;;}}}
;;{{{  fedex, UPS
(emacspeak-url-template-define
 "fedex packages"
 "http://www.fedex.com/cgi-bin/tracking?link=6&pv=ja&action=track&ftc_3=null&template_type=ftc&language=english&last_action=track&ascend_header=1&cntry_code=us&initial=x&mps=y&ascend_header=1&cntry_code=us&initial=x&tracknumber_list=%s"
 (list "Tracking Number: ")
 nil
 "Display package tracking information from Fedex.")

(emacspeak-url-template-define
 "UPS Packages"
 "http://wwwapps.ups.com/WebTracking/processInputRequest?HTMLVersion=5.0&sort_by=status&tracknums_displayed=5&TypeOfInquiryNumber=T&loc=en_US&InquiryNumber1=%s&InquiryNumber2=&InquiryNumber3=&InquiryNumber4=&InquiryNumber5=&track.x=0&track.y=0&AgreeToTermsAndConditions=yes"
 (list "Tracking Number: ")
 nil
 "Display package tracking information from UPS."
 #'(lambda (url)
     (emacspeak-we-extract-by-class "dataTable" url 'speak)))

;;}}}
;;{{{ amazon
(emacspeak-url-template-define
 "Amazon Product Details By ASIN"
 "http://amazon.com/o/dt/upda-1.0-i/tg/aa/upda/item/-/%s"
 (list "ASIN Or ISBN: ")
 nil
 "Retrieve product details from Amazon by either ISBN or ASIN.")
;;}}}
;;{{{ bookshare
;;; replacing with API  client:

(defun emacspeak-url-template-calendar-to-seconds ()
  "Convert date under cursor to seconds since epoch."
  (unless (eq 'calendar-mode  major-mode)
    (error "Not in the calendar."))
  (let ((date (calendar-cursor-to-date)))
    (format "%d"
            (float-time
             (encode-time 0 0 0
                          (second date)
                          (first date)
                          (third date)))))        )

;;}}}
;;{{{ shoutcast
(defvar emacspeak-url-template-shoutcast-history nil
  "History to track shoutcast searchses.")

(emacspeak-url-template-define
 "Shoutcast Search"
 "http://yp.shoutcast.com/directory?s=%s&l=25"
 (list
  #'(lambda ()
      (let ((query
             (read-from-minibuffer "Shoutcast search: "
                                   (car
                                    emacspeak-url-template-shoutcast-history)
                                   nil nil
                                   'emacspeak-url-template-shoutcast-history)))
        (pushnew query emacspeak-url-template-shoutcast-history
                 :test #'string-equal)
        (emacspeak-url-encode query))))
 nil
 "Locate and display Shoutcast streams."
 #'(lambda (url)
     (emacspeak-we-extract-table-by-match
      "Rank"
      url
      'speak)))

;;}}}
;;{{{  old time radio
(emacspeak-url-template-define
 "Old Time Radio"
 "http://www.oldtimeradioprograms.com"
 nil
 nil
 "This months Old Time Radio Programing"
 #'(lambda (url)
     (emacspeak-we-extract-nested-table-list
      (list 2 3 )
      url)))
;;}}}
;;{{{ Netcraft surveys
(emacspeak-url-template-define
 "Netcraft Web Analysis"
 "http://uptime.netcraft.com/up/graph?display=uptime&site=%s"
 (list "Site to analyze: ")
 nil
 "Analyze WWW site using Netcraft."
 #'(lambda (url)
     (emacspeak-we-extract-tables-by-match-list
      (list "running" "average")
      url 'speak)))

(emacspeak-url-template-define
 "Netcraft Site Report"
 "http://toolbar.netcraft.com/site_report?url=%s"
 (list "Site Report: ")
 'emacspeak-speak-buffer
 "Analyze WWW site using Netcraft."
 nil
 'dont-url-encode)

;;}}}
;;{{{  digg

(emacspeak-url-template-define
 "Digg"
 "http://www.digg.org/rss/index.xml"
 nil
 nil
 "Display Digg Feed."
 'emacspeak-webutils-rss-display)

;;}}}
;;{{{ BBC iPlayer 
;;; convertor is here:
;;; http://www.iplayerconverter.co.uk/convert.aspx

(defvar emacspeak-url-template-iplayer-convertor
  "http://www.iplayerconverter.co.uk/pid/%s/r/stream.aspx"
  "Template for generating persistent realplayer URL for iplayer content.")

(defun emacspeak-url-template-iplayer-player (cid)
  "Take a cid particle, and invokes mplayer."
  (declare (special emacspeak-url-template-iplayer-convertor))
  (let ((handle (format emacspeak-url-template-iplayer-convertor (substring  cid 4))))
    (emacspeak-m-player handle 'playlist)
    (message handle)))

(emacspeak-url-template-define
 "BBC  iPlayer"
 "http://www.bbc.co.uk/%s/programmes/schedules/%s%s.xml"
 (list
  "Station: "
  #'(lambda ()
      (let ((outlet (read-from-minibuffer "Outlet: ")))
        (cond
         ((= 0 (length outlet)) outlet)
         (t (concat outlet "/")))))
  'emacspeak-url-template-date-year/month/date)
 #'(lambda ()
     (declare (special emacspeak-we-url-executor))
     (setq emacspeak-we-url-executor
           'emacspeak-url-template-iplayer-player))
 "BBC iPlayer"
 #'(lambda (url)
     (emacspeak-webutils-with-xsl-environment
      (expand-file-name "bbc-iplayer.xsl" emacspeak-xslt-directory)
      nil emacspeak-xslt-options
      (browse-url url))))

;;}}}
;;{{{ bbc
(emacspeak-url-template-define
 "Mobile BBC"
 "http://www.bbc.co.uk/mobile/radio/listen/"
 nil
 nil
 "BBC Mobile Streams.")

(emacspeak-url-template-define
 "BBC  7 Radio Bridge"
 "rtsp://rmv8.bbc.net.uk:554/bbc7coyopa/bbc7_-_%s_%s.ra"
 (list
  "Weekeday: "
  "Time: ")
 nil
 "Play BBC  Radio7 show for a given day/time."
 'emacspeak-m-player)

(emacspeak-url-template-define
 "Radio4 radioBridge"
 "rtsp://rmv8.bbc.net.uk:554/radio4fmcoyopa/radio_4_fm_-_%s_%s.ra"
 (list
  "Weekeday: "
  "Time: ")
 nil
 "Play BBC  Radio4 show for a given day/time."
 'emacspeak-m-player)

;;}}}
;;{{{  answers.com
(emacspeak-url-template-define
 "Answers.com"
 "http://www.answers.com/main/ntquery?s=%s"
 (list "Search answers.com for: ")
 nil
 "Search answers.com")

;;}}}
;;{{{ html5irc 

(emacspeak-url-template-define
 "html5IRC"
 "http://krijnhoetmer.nl/irc-logs/whatwg/%s"
 (list 'emacspeak-url-template-date-YearMonthDate)
 nil
 "Show HTML5 IRC log.")

;;}}}
;;{{{ product search: Google (used to be  froogle)

(emacspeak-url-template-define
 "Google Product Search"
 "https://www.google.com/products?q=%s&output=html"
 (list "Product: ")
 #'(lambda ()
     (search-forward "Please" nil t)
     (forward-line 2)
     (emacspeak-speak-line))
 "Perform Google Product Search"
 #'(lambda (url)
     (emacspeak-we-xslt-filter
      "id(\"res0\")/.."
      url )))

;;; Google Realtime standalone:

(emacspeak-url-template-define
 "Google Realtime Search"
 "http://www.google.com/search?tbs=mbl:1&hl=en&source=hp&ie=ISO-8859-1&q=%s&btnG=Search"
 (list "Realtime Search: ")
 #'(lambda ()
     (re-search-forward "^ *New Results" nil t)
     (emacspeak-speak-rest-of-buffer))
 "Perform Google Realtime Search"
 )

;;}}}
;;{{{ market summary from google finance

(emacspeak-url-template-define
 "Market summary from Google"
 "http://finance.google.com/finance"
 nil
 nil
 "Display financial market summary."
 #'(lambda (url)
     (let ((w3-auto-image-alt nil))
       (emacspeak-we-extract-by-class
        "id-summary-chart" url 'speak))))

;;}}}
;;{{{ google CSE and Google Reader:
(defcustom emacspeak-url-template-reading-list-opml nil
  "OPML feed location to use for our Custom Search."
  :type '(choice
          (const :tag "None" nil)
          (string :tag "URL"))
  :group 'emacspeak-url-template)

(defsubst emacspeak-url-template-make-cse (meta-url)
  "Builds up a CSE url for specified meta-url."
  (format
   "http://www.google.com/cse/tools/makecse?url=%s"
   meta-url))

(emacspeak-url-template-define
 "Reader Subscription Search"
 "http://www.google.com/cse?q=%s&loading=1&cref=%s"
 (list
  "Reader Search: "
  #'(lambda nil
      (declare
       (special emacspeak-url-template-reading-list-opml))
      (emacspeak-url-template-make-cse
       (emacspeak-url-encode emacspeak-url-template-reading-list-opml))))
 nil
 "Search within feeds subscribed to in Google Reader."
 #'(lambda (url)
     (emacspeak-we-extract-by-class "g" url 'speak)))

(emacspeak-url-template-define
 "Official GoogleBlog Search"
 "http://www.google.com/cse?q=%s&loading=1&cref=%s"
 (list
  "GoogleBlog Search: "
  #'(lambda nil
      (emacspeak-url-template-make-cse
       "http://www.google.com/reader/public/subscriptions/user/10949413115399023739/label/officialgoogleblogs-all")))
 nil
 "Search within all official Google blogs."
 #'(lambda (url)
     (emacspeak-we-extract-by-class "g" url 'speak)))

(emacspeak-url-template-define
 "On The Fly CSE"
 "http://www.google.com/cse?q=%s&loading=1&cref=%s"
 (list
  "Search This CSE: "
  #'(lambda nil
      (emacspeak-url-template-make-cse
       (read-from-minibuffer
        "Feed URL to build CSE for: "))))
 nil
 "Build a CSE on the fly and  use it to search."
 #'(lambda (url)
     (emacspeak-we-extract-by-class "g" url 'speak)))

;;}}}
;;{{{ utils:

(defun emacspeak-url-template-setup-content-filter ()
  "Set up content filter in displayed page."
  (declare (special emacspeak-we-xpath-filter emacspeak-we-paragraphs-xpath-filter))
  (setq emacspeak-we-xpath-filter
        emacspeak-we-paragraphs-xpath-filter))

;;}}}
;;{{{ webmaster tools
(emacspeak-url-template-define
 "Google Webmaster Page Analysis"
 "https://www.google.com/webmasters/tools/pageanalysis?siteUrl=%s"
 (list "URL To Analyze: ")
 nil
 "Page Analysis From Google Webmaster tools.")

;;}}}
;;{{{ Google views

(emacspeak-url-template-define
 "Google TimeLine View"
 "http://www.google.com/search?hl=en&tbo=1&tbs=tl:1&q=%s"
 (list
  'gweb-google-autocomplete)
 #'(lambda nil
     (goto-char (point-min))
     (re-search-forward " ^About" nil t)
     (forward-line 1)
     (emacspeak-speak-rest-of-buffer))
 "Do a Google search and get a timeline view of results.")
(emacspeak-url-template-define
 "Google Info View"
 "http://www.google.com/views?q=%s+view:info&sa=N&ct=infoview"
 (list
  'gweb-google-autocomplete)
 #'(lambda nil
     (re-search-forward "Info View" nil t)
     (forward-line 1)
     (emacspeak-speak-rest-of-buffer))
 "Do a Google search and get a Info view of results.")

;;}}}

;;{{{ Anonimize google search

(emacspeak-url-template-define
 "Anonymize Google Search"
 "http://www.google.com/accounts/Logout"
 nil
 nil
 "Logout from Google to do an anonymous search.")

;;}}}
;;{{{ gmail: Mobile

(emacspeak-url-template-define
 "GMail Mobile"
 "http://mail.google.com/mail/x/"
 nil
 'emacspeak-speak-buffer
 "GMail Mobile XHTML version --- light-weight, fast!")

;;}}}
;;{{{ GMail HTML

(defcustom emacspeak-url-template-gmail-search-url
  "https://mail.google.com/mail/h/"
  "URL eng-point for GMail searches.
For  corporate email using GMail, change /a/google.com/ to /a/<your.domain>/"   
  :type '(choice
          (string :tag "GMail"  "https://mail.google.com/mail/")
          (string :tag "Corporate"  "https://mail.google.com/a/google.com/h/"))
  :group 'emacspeak-url-template)

(emacspeak-url-template-define
 "GMail Search"
 (concat emacspeak-url-template-gmail-search-url
         "?ui=html&s=q&q=%s&nvp_site_mail=Search+Mail&f=1")
 (list "GMail Search:")
 #'(lambda ()
     (declare (special emacspeak-we-class-filter
                       emacspeak-we-url-rewrite-rule))
     (setq emacspeak-we-url-rewrite-rule '("$" "&ui=html"))
     (setq emacspeak-we-class-filter "msg")
     )
 "Search GMail. 
Make sure to sign in before invoking this template."
 #'(lambda (url)
     (emacspeak-we-extract-by-class "th"  url 'speak)))

(emacspeak-url-template-define
 "GMail Labels"
 "http://mail.google.com/mail/h/1m84rgwrg8118/?s=l&l=%s"
 (list "GMail Label:")
 #'(lambda ()
     (declare (special emacspeak-we-class-filter))
     (setq emacspeak-we-class-filter "msg"))
 "Find messages having label from GMail. 
Make sure to sign in before invoking this template."
 #'(lambda (url)
     (emacspeak-we-xslt-filter "//form" url 'speak)))

(emacspeak-url-template-define
 "GMail Contacts"
 (concat emacspeak-url-template-gmail-search-url
         "?v=cl&pnl=a")
 nil
 nil
 "Open GMail Inbox"
 #'(lambda (url)
     (emacspeak-we-extract-by-class "th" url )))

(emacspeak-url-template-define
 "GMail Inbox"
 (concat emacspeak-url-template-gmail-search-url
         "h/")
 nil
 #'(lambda ()
     (declare (special emacspeak-we-class-filter))
     (setq emacspeak-we-class-filter "msg"))
 "Open GMail Inbox"
 #'(lambda (url)
     (emacspeak-we-xslt-filter "//form"
                               url 'speak)))

;;}}}
;;{{{ Calendar Mobile:

(defcustom emacspeak-url-template-google-calendar-uri
  "http://www.google.com/calendar/m?output=xhtml&pli=1"
  "URI for accessing mobile version of Google Calendar.
Google Apps users should set this to
http://www.google.com/calendar/a/<my-corp>/m?output=xhtml"
  :type 'string
  :group 'emacspeak-url-template)

(emacspeak-url-template-define
 "GCalendar Mobile"
 emacspeak-url-template-google-calendar-uri
 nil
 'emacspeak-speak-buffer
 "Google Calendar XHTML version.")

;;}}}
;;{{{  google patent search:

(emacspeak-url-template-define
 "Patent Search From Google"
 "http://www.google.com/patents?ie=ISO-8859-1&q=%s"
 (list "Google For Patents: ")
 #'(lambda nil
     (search-forward " Patent Search" nil t)
     (beginning-of-line)
     (emacspeak-speak-rest-of-buffer))
 "Perform patent search via Google")

;;}}}
;;{{{ google code search

(emacspeak-url-template-define
 "Google API Search"
 "http://www.google.com/cse?cx=001456098540849067467%%3A6whlsytkdqg&cof=FORID%%3A0&q=%s&sa=Search"
 (list "Google API Search: ")
 nil
 "Search Google APIDocs")

(emacspeak-url-template-define
 "Code Search From Google"
 "http://www.google.com/codesearch?q=%s"
 (list "Google For Code: ")
 #'(lambda nil
     (search-forward "results"  )
     (emacspeak-speak-line))
 "Search using Google Code Search."
 #'(lambda (url)
     (emacspeak-webutils-without-xsl (browse-url url))))

;;}}}
;;{{{ google music:

(emacspeak-url-template-define
 "Music Search"
 "http://www.google.com/musicsearch?q=%s"
 (list "Google Music Search:")
 #'(lambda nil
     (search-forward "results"  )
     (emacspeak-speak-line))
 "Music search on Google."
 #'(lambda (url)
     (emacspeak-webutils-without-xsl
      (browse-url url))))

;;}}}
;;{{{ YouTube:
(emacspeak-url-template-define
 "YouTube Results"
 "http://gdata.youtube.com/feeds/api/videos?vq=%s"
 (list
  #'(lambda ()
      (gweb-google-autocomplete-with-corpus "youtube")))
 #'(lambda ()
     (declare (special emacspeak-we-url-executor))
     (setq emacspeak-we-url-executor
           'emacspeak-m-player-youtube-player))
 "YouTube Search Via Feeds"
 'emacspeak-webutils-atom-display)

(emacspeak-url-template-define
 "Recent YouTube Results"
 "http://gdata.youtube.com/feeds/api/videos?vq=%s&orderby=updated"
 (list "YouTube:")
 #'(lambda ()
     (declare (special emacspeak-we-url-executor))
     (setq emacspeak-we-url-executor
           'emacspeak-m-player-youtube-player))
 "YouTube Search Via Feeds"
 'emacspeak-webutils-atom-display)

;;}}}
;;{{{  Google Video:

(emacspeak-url-template-define
 "Google Soccer Results"
 "http://www.google.com/search?q=%s+world+cup+soccer&num=1"
 (list "Countries:")
 nil
 "Display World Cup Soccer Results for specified countries."
 #'(lambda (url)
     (emacspeak-we-extract-nested-table 5 url 'speak)))

(emacspeak-url-template-define
 "Google Video"
 "http://video.google.com/videofeed?type=search&q=%s&num=20&output=rss"
 (list "Video Search:")
 nil
 "Retrieve Google Video search results as an atom feed."
 'emacspeak-webutils-rss-display)

;;}}}
;;{{{ Google Reader:

(emacspeak-url-template-define
 "Google Reader"
 "http://www.google.com/reader/public/atom/feed/%s?n=100"
 (list 'emacspeak-webutils-read-this-url )
 nil
 "Google Reader"
 'emacspeak-webutils-atom-display)

;;}}}
;;{{{ google finance
;;{{{ seeking alpha stock search

(emacspeak-url-template-define
 "Seeking Alpha Stock Search"
 "http://seekingalpha.com/search/?cx=001514237567335583750%%3Acdhc2yeo2ko&cof=FORID%%3A11%%3BNB%%3A1&q=%s"
 (list "Company:")
 nil
 "Seeking Alpha search.")

;;}}}
;;; pull google finance search results via the transcoder

(emacspeak-url-template-define
 "Mobile Finance Google Search"
 "http://finance.google.com/finance?q=%s"
 (list "Finance Search: ")
 #'(lambda nil
     (call-interactively 'emacspeak-imenu-goto-next-index-position))
 "Display content from Google Finance."
 #'(lambda (url)
     (browse-url
      (format emacspeak-webutils-google-transcoder-url
              (emacspeak-url-encode
               url)))))

(emacspeak-url-template-define
 "Finance Google Search"
 "http://finance.google.com/finance?q=%s"
 (list "Finance Search: ")
 nil
 "Display content from Google Finance."
 )

(defun emacspeak-finance-google-up-or-down (value)
  "Return up/down by value."
  (let ((minus-p (string-match "-" value)))
    (cond
     (minus-p
      (format " down  %s"
              (substring value (1+ minus-p ))))
     (t (format " up  %s " value)))))

(defvar emacspeak-google-finance-row-filter
  '(0 (emacspeak-finance-google-up-or-down 3)" to " 2  " for  a market cap of " 4 
      "Traded today between " 8 " and " 7 " on a  volume of " 5)
  "Template used as a row formatter for Finance Portfolios.")

(emacspeak-url-template-define
 "Finance Google Portfolio"
 "http://finance.google.com/finance/portfolio?action=view&pid=1&pview=sview&output=csv"
 nil nil
 "Download and display portfolio from Google Finance."
 #'(lambda (url)
     (declare (special emacspeak-google-finance-row-filter
                       emacspeak-table-speak-row-filter))
     (let ((buffer (url-retrieve-synchronously url)))
       (save-excursion
         (set-buffer buffer)
         (goto-char (point-min))
         (search-forward "\n\n")
         (delete-region (point-min) (point))
         (emacspeak-table-view-csv-buffer buffer)
         (kill-buffer buffer)
         (when (get-buffer "Portfolio From Google Finance")
           (kill-buffer "Portfolio From Google Finance"))
         (rename-buffer "Portfolio From Google Finance")
         (setq tab-width 12
               emacspeak-table-speak-row-filter
               emacspeak-google-finance-row-filter)
         (emacspeak-table-next-row)))))

(emacspeak-url-template-define
 "Finance Google news"
 "http://finance.google.com/"
 nil
 nil
 "Display content from Google Finance."
 #'(lambda (url)
     (emacspeak-we-extract-by-class
      "news" url 'speak)))

;;}}}
;;{{{ google maps

;;; public transit using Google Maps:

(emacspeak-url-template-define
 "Public Transit Via Google Maps"
 "http://www.google.com/maps?output=html&ie=UTF8&f=d&dirflg=r&q=%s&ttype=dep&date=%s&time=now"
 (list
  "Trip Details: "
  #'(lambda ()
      (emacspeak-url-encode
       (format-time-string "%m/%d/%y"))))
 nil
 "Public transit directions from Google."
 #'(lambda (url)
     (emacspeak-we-extract-by-class "directions"
                                    url 'speak)))

(emacspeak-url-template-define
 "Walking Directions From Google"
 "http://maps.google.com/maps?f=d&output=html&hl=en&q=%s&dirmode=walking&ie=UTF8&dirflg=w"
 (list "Route: ")
 nil
 "Display walking directions using Google."
 #'(lambda (url)
     (emacspeak-we-extract-by-class "dir" url 'speak)))

(emacspeak-url-template-define
 "EmapSpeak Via Google"
 "http://maps.google.com/maps?q=%s&output=kml"
 (list "Query: ")
 'emacspeak-speak-buffer
 "EmapSpeak Via Google.

Specify the query using English and  addresses as complete as
  possible.

Here are some examples:

0) To find a location by address specify:

650 Harry Road San Jose CA 95120

1) To get directions, specify:

<source address> to <destination address>

2) To find businesses etc., near a location, specify:

<what> near <location address>
"
 #'(lambda (url)
     (let ((buffer
            (emacspeak-xslt-xml-url
             (expand-file-name "kml2html.xsl" emacspeak-xslt-directory)
             url )))
       (browse-url-of-buffer buffer))))

;;}}}
;;{{{ google scholar

(emacspeak-url-template-define
 "Google Books"
 "http://books.google.com/books?q=%s&btnG=Search+Books&hl=en&output=html_text"
 (list "Google Book Search: ")
 #'(lambda nil
     (emacspeak-imenu-goto-next-index-position)
     (emacspeak-speak-rest-of-buffer))
 "Google Books Search with text when available")

(emacspeak-url-template-define
 "Google Scholar"
 "http://scholar.google.com/scholar?ie=UTF-8&oe=UTF-8&hl=en&btnG=Search&num=25&q=%s"
 (list "Google Scholar Search: ")
 nil
 "Google Scholar Search"
 #'(lambda (url)
     (emacspeak-we-extract-by-class "gs_r" url 'speak)))

;;}}}
;;{{{ google images

(emacspeak-url-template-define
 "Google Image Search"
 "http://images.google.com/images?hl=en&source=hp&q=%s&btnG=Search+Images&gbv=1"
 (list "Google Image Search: ")
 #'(lambda ()
     (search-forward "results" nil t)
     (emacspeak-speak-line))
 "Google Image Search"
 #'(lambda (url)
     (emacspeak-webutils-without-xsl
      (browse-url url))))

;;}}}
;;{{{ googl blogsearch

(emacspeak-url-template-define
 "BlogSearch Google"
 "http://www.google.com/search?q=%s&hl=en&tbm=blg&output=atom"
 (list "Google Blog Search: ")
 nil
 "Google Blog Search"
 'emacspeak-webutils-atom-display)
(emacspeak-url-template-define
 "Recent BlogSearch Google"
 "http://www.google.com/search?q=%s&hl=en&tbm=blg&scoring=d&output=atom"
 (list "Google Blog Search: ")
 nil
 "Google Blog Search"
 'emacspeak-webutils-atom-display)

;;}}}
;;{{{ google translation service

(emacspeak-url-template-define
 "Multilingual dictionary via Google."
 "http://translate.google.com/translate_dict?q=%s&sa=N&hl=en&langpair=%s"
 (list
  "Word: "
  "Translate from|To:")
 nil
 "Translate word using Google.
Source and target languages
are specified as two-letter language codes, e.g. en|de translates
from English to German")

(emacspeak-url-template-define
 "Translation Via Google"
 "http://translate.google.com/translate_c?hl=en&langpair=%s&u=%s"
 (list
  "Translate from|To:"
  "URI: ")
 nil
 "Translate a Web page using google. Source and target languages
are specified as two-letter language codes, e.g. en|de translates
from English to German.")

;;}}}
;;{{{ dictionary.com:
(emacspeak-url-template-define
 "Dictionary Lookup"
 "http://dictionary.reference.com/search?q=%s"
 (list "Dictionary Lookup: ")
 #'(lambda ()
     (search-forward "entries found for " nil t)
     (emacspeak-speak-line))
 "Dictionary Lookup"
 #'(lambda (url)
     (emacspeak-webutils-without-xsl
      (browse-url url))))

;;}}}
;;{{{ yubnub
(emacspeak-url-template-define
 "YubNub Web Command Line"
 "http://yubnub.org/parser/parse?command=%s"
 (list "YubNub Command: ")
 nil
 "YubNub Command Line"
 )

;;}}}
;;{{{ Google Reader:

(emacspeak-url-template-define
 "Google Reader"
 "http://www.google.com/reader/public/atom/feed/%s"
 (list "Feed: ")
 nil
 "View feed via Google Reader."
 'emacspeak-webutils-atom-display)

;;}}}
;;{{{  google filters
(emacspeak-url-template-define
 "Google WebQuotes"
 "http://labs.google.com/cgi-bin/webquotes?num_quotes=3&q=%s&btnG=Google+WebQuotes+Search&show_titles=1&bold_links=1&snippet_threshold=3"
 (list "Query: ")
 nil
 "Google WebQuotes.")
(emacspeak-url-template-define
 "Google Glossary"
 "http://labs.google.com/glossary?q=%s"
 (list "Term: ")
 nil
 "Google Glossary lookup.")

(emacspeak-url-template-define
 "Google Results"
 "http://www.google.com/search?q=%s&num=25"
 (list 'gweb-google-autocomplete)
 nil
 "Show just results and nav bar."
 #'(lambda (url)
     (emacspeak-we-extract-by-id-list
      (list "subform_ctrl" "res" "nav")
      url 'speak)))

(emacspeak-url-template-define
 "1Box Google"
 "http://www.google.com/search?q=%s"
 (list 'gweb-google-autocomplete)
 nil
 "Show 1box result from Google. Actually now shows just the results."
 #'(lambda (url)
     (emacspeak-we-extract-by-id
      "res"
      url 'speak)))

(emacspeak-url-template-define
 "Google Hits"
 "http://www.google.com/search?q=%s&num=%s"
 (list 'gweb-google-autocomplete
       #'(lambda nil
           (declare (special  emacspeak-websearch-google-number-of-results))
           emacspeak-websearch-google-number-of-results))
 nil
 "Only show Google hits."
 #'(lambda (url)
     (emacspeak-we-extract-by-id "res"
                                 url 'speak)))

;;}}}
;;{{{ NY Times
(emacspeak-url-template-define
 "NY Times RSS Feeds"
 "http://www.nytimes.com/services/xml/rss/nyt/index.opml"
 nil
 nil
 "Display browsable list of NY Times RSS Feeds."
 #'(lambda (url)
     (let ((buffer
            (emacspeak-xslt-xml-url
             (expand-file-name "opml.xsl"
                               emacspeak-xslt-directory)
             url )))
       (save-excursion
         (set-buffer buffer)
         (browse-url-of-buffer)))))

;;}}}
;;{{{ Google Local:

(emacspeak-url-template-define
 "Google Local"
 "http://local.google.com/local?output=html&q=%s"
 (list "Google Local Search:")
 #'(lambda ()
     (search-forward "Local Search within" nil t)
     (emacspeak-speak-line))
 "Google Local Search.")

;;}}}
;;{{{ google OverviewOfNews

(emacspeak-url-template-define
 "Google Print"
 "http://print.google.com/print?oi=print&q=%s"
 (list "Google Print Search:")
 #'(lambda nil
     (search-forward "Print  Books" nil t)
     (emacspeak-speak-rest-of-buffer))
 "Google Print Search")

(emacspeak-url-template-define
 "Google Text  News"
 "http://news.google.com/news?ned=tus"
 nil
 #'(lambda nil
     (emacspeak-speak-rest-of-buffer))
 "Retrieve and speak Google News Overview."
 #'(lambda (url)
     (emacspeak-webutils-without-xsl
      (browse-url url))))

(emacspeak-url-template-define
 "Google News Search"
 "http://news.google.com/news?hl=en&ned=tus&q=%s&btnG=Google+Search&output=atom"
 (list 'gweb-news-autocomplete)
 'emacspeak-url-template-setup-content-filter
 "Search Google news."
 'emacspeak-webutils-atom-display)

(emacspeak-url-template-define
 "Google Recent News Search"
 "http://news.google.com/news?hl=en&ned=tus&q=%s&scoring=d&output=atom"
 (list "Search news for: ")
 nil
 "Search Google news."
 #'(lambda (url)
     (emacspeak-webutils-atom-display url )))

(emacspeak-url-template-define
 "Google Mobile Search"
 "http://www.google.com/xhtml?q=%s&site=search&mrestrict=xhtml&num=25"
 (list "Search For: ")
 #'(lambda ()
     (re-search-forward "^Results" nil t)
     (emacspeak-speak-rest-of-buffer))
 "Google Mobile Search")

(defvar emacspeak-url-template-google-transcoder-url
  "http://www.google.com/gwt/n?_gwt_noimg=1&output=xhtml&u=%s"
  "URL for  obtaining mobile transcoder page views.")

(emacspeak-url-template-define
 "Google Transcoder"
 emacspeak-url-template-google-transcoder-url
 (list
  #'(lambda ()
      (read-from-minibuffer "URL: "
                            (or (browse-url-url-at-point)
                                "http://"))))
 'emacspeak-speak-buffer
 "Transcode site via Google.")

(emacspeak-url-template-define
 "Google topical  News"
 "http://news.google.com/news?ned=us&topic=%s&output=atom"
 (list "Topic Code: ")
 nil
 "Display specified news feed."
 'emacspeak-webutils-atom-display)

(emacspeak-url-template-define
 "Google Feeds"
 "http://news.google.com/intl/en_us/news_feed_terms.html"
 nil
 nil
 "List  Google news Feeds."
 #'(lambda (url)
     (emacspeak-we-extract-table-by-match "Sports"
                                          url 'speak)))

;;}}}
;;{{{ Google Archive Search

(emacspeak-url-template-define
 "Archive News Search"
 "http://news.google.com/archivesearch?hl=en&sa=N&q=%s"
 (list "Archive News Search: ")
 #'(lambda nil
     (search-forward "Results" nil t)
     (emacspeak-speak-line))
 "Search Google Archive News."
 #'(lambda (url)
     (emacspeak-webutils-without-xsl
      (browse-url url))))

(emacspeak-url-template-define
 "IToRSS"
 "http://feedflipper.net/convert.php?feed=%s"
 (list "ITunes URL: ")
 nil
 "Pull RSS  feed corresponding to an ITunes Podcast."
 'emacspeak-webutils-rss-display)

;;}}}
;;{{{  cnet news

(emacspeak-url-template-define
 "Tech News From CNet"
 "http://news.com.com/2547-1_3-0-5.xml"
 nil
 'emacspeak-url-template-setup-content-filter
 "Display tech news from CNET"
 'emacspeak-webutils-rss-display)

(emacspeak-url-template-define
 "PodCast CNet"
 "http://podcast-files.cnet.com/podcast/cnet_podcast_%s.mp3"
 (list
  #'(lambda nil
      (read-from-minibuffer
       "Date: "
       (format-time-string "%m%d%y"))))
 nil
 "Play Podcast from CNET"
 #'(lambda (url)
     (funcall emacspeak-media-player url)))

;;}}}
;;{{{ Infoworld RSS
(emacspeak-url-template-define
 "InfoWorld RSS Feeds"
 "http://www.infoworld.com/rss/rss_info.html"
 nil
 nil
 "Produce  a set of RSS links published by InfoWorld."
 #'(lambda (url)
     (emacspeak-we-xslt-filter
      "//a[contains(@href, \".rdf\") and @class]"
      url  'speak)))

;;}}}

;;{{{ mapquest

(emacspeak-url-template-define
 "MapQuest Directions"
 "http://www.mapquest.com/directions/main.adp?go=1&do=nw&1y=US&2y=US&ct=NA&1a=%s&1c=%s&1c=%s&1z=%s&2a=%s&2c=%s&2s=%s&2z=%s"
 (list "Start Address:" "City:" "State:" "Zip:"
       "Destination Address:" "City:" "State:" "Zip:")
 nil
 "Retrieve and speak directions from MapQuest."
 #'(lambda (url)
     (emacspeak-we-extract-table-by-match "Maneuvers"
                                          url 'speak)))

;;}}}
;;{{{ bing rss

(emacspeak-url-template-define
 "Bing RSS"
 "http://www.bing.com/search?go=&qs=ns&form=QBLH&format=rss&q=%s"
 (list "Bing For: ")
 nil
 "RSS Feed of Bing Results."
 #'(lambda (url)
     (emacspeak-webutils-rss-display url)))

;;}}}
;;{{{ yahoo daily news
(emacspeak-url-template-define
 "Yahoo RSS Feeds"
 "http://news.yahoo.com/rss"
 nil
 #'(lambda ()
     (emacspeak-pronounce-add-buffer-local-dictionary-entry
      "http://rss.news.yahoo.com/rss/" ""))
 "List Yahoo RSS Feeds."
 #'(lambda (url)
     (emacspeak-we-xslt-filter
      "//a[not(contains(@href,\"url\"))and  contains(@href, \"rss\") ]"
      url 'speak)))

(defun emacspeak-url-template-yahoo-news-processor (url)
  "Process and speak Yahoo news."
  (declare (special emacspeak-web-post-process-hook))
  (add-hook 'emacspeak-web-post-process-hook
            #'(lambda nil
                (declare (special  emacspeak-we-url-rewrite-rule
                                   emacspeak-we-class-filter))
                (setq emacspeak-we-class-filter "article"
                      emacspeak-we-url-rewrite-rule
                      '("$" "&printer=1"))
                (emacspeak-speak-buffer)))
  (emacspeak-we-xslt-filter
   "//*[@id=\"ynmain\"]"
   url))

(emacspeak-url-template-define
 "Yahoo DailyNews"
 "http://dailynews.yahoo.com/"
 nil
 nil
 "Retrieve and speak DailyNewspage from  Yahoo Daily News."
 'emacspeak-url-template-yahoo-news-processor)

(emacspeak-url-template-define
 "Yahoo Politics"
 "http://dailynews.yahoo.com/news?tmpl=index2&cid=703"
 nil
 nil
 "Retrieve and speak Politics section from Yahoo Daily News."
 'emacspeak-url-template-yahoo-news-processor)

(emacspeak-url-template-define
 "Yahoo Entertainment"
 "http://dailynews.yahoo.com/news?tmpl=index2&cid=762"
 nil
 nil
 "Retrieve and speak Entertainment section from Yahoo Daily News."
 'emacspeak-url-template-yahoo-news-processor)

(emacspeak-url-template-define
 "Yahoo Sports"
 "http://dailynews.yahoo.com/news?tmpl=index2&cid=755"
 nil
 nil
 "Entertainment news from Yahoo."
 'emacspeak-url-template-yahoo-news-processor)

(emacspeak-url-template-define
 "Yahoo Business News"
 "http://story.news.yahoo.com/news?tmpl=index&cid=749"
 nil
 nil
 "Retrieve and speak business  section from Yahoo Daily News."
 'emacspeak-url-template-yahoo-news-processor)

(emacspeak-url-template-define
 "Yahoo Science"
 "http://dailynews.yahoo.com/news?tmpl=index2&cid=753"
 nil
 nil
 "Retrieve and speak Science section from Yahoo Daily News."
 'emacspeak-url-template-yahoo-news-processor)

(emacspeak-url-template-define
 "Yahoo SF Local"
 "http://dailynews.yahoo.com/news?tmpl=index2&cid=390"
 nil
 nil
 "Retrieve and speak Local section from Yahoo Daily News."
 'emacspeak-url-template-yahoo-news-processor)

(emacspeak-url-template-define
 "Yahoo Content By Content ID"
 "http://dailynews.yahoo.com/news?tmpl=index2&cid=%s"
 (list "Content ID: ")
 nil
 "Retrieve and speak news section from Yahoo Daily News."
 'emacspeak-url-template-yahoo-news-processor)

(emacspeak-url-template-define
 "Yahoo Top Stories"
 "http://dailynews.yahoo.com/news?tmpl=index2&cid=716"
 nil
 nil
 "Retrieve and speak Top Stories  section from Yahoo Daily News."
 'emacspeak-url-template-yahoo-news-processor)

(emacspeak-url-template-define
 "Yahoo Health"
 "http://dailynews.yahoo.com/news?tmpl=index2&cid=751"
 nil
 nil
 "Retrieve and speak Health section from Yahoo Daily News."
 'emacspeak-url-template-yahoo-news-processor)

(emacspeak-url-template-define
 "Yahoo Oddly"
 "http://dailynews.yahoo.com/news?tmpl=index2&cid=757"
 nil
 nil
 "Retrieve and speak Oddity section from Yahoo Daily News."
 'emacspeak-url-template-yahoo-news-processor)

(emacspeak-url-template-define
 "Yahoo Technology  News"
 "http://dailynews.yahoo.com/news?tmpl=index2&cid=738"
 nil
 nil
 "Yahoo Technology News."
 'emacspeak-url-template-yahoo-news-processor)

(emacspeak-url-template-define
 "Yahoo Lifestyle"
 "http://dailynews.yahoo.com/news?tmpl=index2&cid=811"
 nil
 nil
 "Yahoo Lifestyle News."
 'emacspeak-url-template-yahoo-news-processor)

(emacspeak-url-template-define
 "Yahoo World News"
 "http://dailynews.yahoo.com/news?tmpl=index2&cid=959"
 nil
 nil
 "Yahoo World News."
 'emacspeak-url-template-yahoo-news-processor)

;;}}}
;;{{{ Adobe pdf conversion

(emacspeak-url-template-define
 "pdf2txt"
 "http://access.adobe.com/access/convert.do?acceptLanguage=en&srcPdfUrl=%s&convertTo=text&visuallyImpaired=true&preferHTMLReason=&platform=Linux&comments=&submit=Convert"
 (list "PDF URL: ")
 nil
 "Use access.adobe.com to  convert a remote PDF document to plain
 text.
The PDF document needs to be available on the public Internet.")

(emacspeak-url-template-define
 "pdf2html"
 "http://access.adobe.com/access/convert.do?acceptLanguage=en&srcPdfUrl=%s&convertTo=html&visuallyImpaired=true&preferHTMLReason=&platform=Linux&comments=&submit=Convert"
 (list "PDF URL: ")
 nil
 "Use access.adobe.com to  convert a remote PDF document to plain
 text.
The PDF document needs to be available on the public Internet.")

;;}}}
;;{{{ w3c

(emacspeak-url-template-define
 "w3c IRC Logs"
 "http://www.w3.org/%s-%s-irc "
 (list
  #'(lambda nil
      (emacspeak-url-template-collect-date "Date: "
                                           "%Y/%m/%d"))
  "Channel Name: ")
 #'(lambda ()
     (let ((inhibit-read-only t))
       (flush-lines "has joined #" (point-min) (point-max))
       (flush-lines "has left #" (point-min) (point-max))))
 "Use this to pull up the
archived  logs from the W3C IRC. You need to know the exact
name of the channel.")

(emacspeak-url-template-define
 "w3c Lists"
 "http://lists.w3.org/Archives/Member/%s/%s/"
 (list
  'emacspeak-url-template-get-w3c-group
  'emacspeak-url-template-get-w3c-year/month)
 nil
 "Use this to pull up the
archived  mail from the W3C list. You need to know the exact
name of the list.")

(defun emacspeak-url-template-get-w3c-group ()
  "Get name of W3C group "
  (read-from-minibuffer "W3C group: "
                        "w3c-"))

(defun emacspeak-url-template-get-w3c-year/month ()
  "Get year/month"
  (emacspeak-url-template-collect-date "Date range: "
                                       "%Y%h"))

;;}}}
;;{{{ cnn

(emacspeak-url-template-define
 "CNNPodCasts"
 "http://www.cnn.com/services/podcasting/"
 nil
 nil
 "List CNN Podcast media links."
 #'(lambda (url)
     (emacspeak-we-extract-by-class-list
      '("cnnPODcastleft"
        "cnnPODcastright")
      url
      'speak )))

(emacspeak-url-template-define
 "CNNContent"
 "http://www.cnn.com/"
 nil
 nil
 "Filter down to CNN  content area."
 #'(lambda (url)
     (emacspeak-we-extract-by-id "cnn_maincntnr"url 'speak)))

(emacspeak-url-template-define
 "CNN headlines "
 "http://www.cnn.com"
 nil
 nil
 "Retrieve and speak headline news from CNN."
 #'(lambda (url)
     (emacspeak-we-extract-by-class "cnnMainT1" url 'speak)))

(defun emacspeak-url-template-date-YearMonthDate ()
  "Return today as yyyymmdd"
  (emacspeak-url-template-collect-date "Date:"
                                       "%Y%m%d"))

(defun emacspeak-url-template-date-year/month/date ()
  "Return today as yyyy/mm/dd"
  (emacspeak-url-template-collect-date "Date:"
                                       "%Y/%m/%d"))

(defun emacspeak-url-template-date-month/date ()
  "Return today as mm/dd"
  (emacspeak-url-template-collect-date "Date:"
                                       "%m/%d") )

(emacspeak-url-template-define
 "CNN technology "
 "http://www.cnn.com/TECH/"
 nil
 #'(lambda nil
     (declare (special emacspeak-we-class-filter))
     (setq emacspeak-we-class-filter "cnnStoryContent"))
 "CNN Technology news."
 #'(lambda (url)
     (emacspeak-we-extract-by-class-list
      (list
       "cnnSectT2s"
       "cnnSectT2head"
       "cnnSectBoxHeadW"
       "cnnSectBox")
      url 'speak)))

(emacspeak-url-template-define
 "CNN Market Data "
 "http://money.cnn.com/markets/data/"
 nil
 nil
 "CNN Money"
 #'(lambda (url)
     (emacspeak-we-extract-by-id
      "wsod_marketsOverview" 
      url 'speak)))

(emacspeak-url-template-define
 "CNN Content "
 "http://www.cnn.com/"
 nil
 nil
 "CNN Content"
 #'(lambda (url)
     (emacspeak-we-extract-by-id
      "cnn_maincntnr"
      url
      'speak)))

(emacspeak-url-template-define
 "Money Content "
 "http://money.cnn.com/"
 nil
 'emacspeak-url-template-setup-content-filter
 "CNN Content"
 #'(lambda (url)
     (emacspeak-we-extract-by-id
      "cnnMoneyBody"
      url
      'speak)))

;;}}}
;;{{{ pbs --pulpit
(emacspeak-url-template-define
 "Pulpit --- I Cringely"
 "http://www.pbs.org/cringely/pulpit/pulpit%s.html"
 (list
  #'(lambda nil
      (emacspeak-url-template-collect-date "Date: (most recent Thursday)"
                                           "%Y%m%d")))
 nil
 "Read pulpit from PBS. Published on the Thursday of the week."
 #'(lambda (url)
     (emacspeak-we-xslt-filter
      emacspeak-we-recent-xpath-filter url 'speak)))

;;}}}
;;{{{  The Linux Show
(emacspeak-url-template-define
 "Geek Linux Daily"
 "http://thelinuxdaily.com/shows/%s.m3u"
 (list
  #'(lambda ()
      (emacspeak-url-template-collect-date "Date:"
                                           "%Y/%m/%d")))
 nil
 "Play specified edition of Geek  Linux DailyShow"
 #'(lambda (url)
     (funcall emacspeak-media-player url 'play-list)))

(emacspeak-url-template-define
 "Redhat Linux Show"
 "http://www.thelinuxshow.com/archives/%s.mp3"
 (list
  #'(lambda ()
      (let ((mm-dd-yy
             (emacspeak-url-template-collect-date
              "Date: (Tuesday)"
              "%m-%d-%Y")))
        (format "%s/tls-%s"
                (third (split-string mm-dd-yy "-"))
                mm-dd-yy))))
 nil
 "Play specified edition of Redhat Linux Show"
 #'(lambda (url)
     (funcall emacspeak-media-player url 'play-list)))

;;}}}
;;{{{ technet cast from DDJ

(emacspeak-url-template-define
 "DDJ TechNetCast Save"
 "http://technetcast.ddj.com/tnc_save_mp3.html?stream_id=%s"
 (list "Download Stream ")
 nil
 "Browse to a specified DDJ Technetcast stream and save  it.")

(emacspeak-url-template-define
 "DDJ TechNetCast Play"
 "http://technetcast.ddj.com/tnc_play.m3u?stream_id=%s"
 (list "Stream Id")
 nil
 "Play Technetcast stream from DDJ."
 #'(lambda (url)
     (funcall emacspeak-media-player  url 'play-list)))

;;}}}
;;{{{  linux today

(emacspeak-url-template-define
 "Linux Today News"
 "http://www.linuxtoday.com/"
 nil
 nil
 "Get news column from Linux Today."
 #'(lambda (url)
     (emacspeak-we-xslt-filter
      "(//table)[2]/tr/td[2]"
      url
      'speak)))

;;}}}
;;{{{ sourceforge

(emacspeak-url-template-define
 "sourceforge project"
 "http://sourceforge.net/projects/%s"
 (list "Project name")
 nil
 "Open specified project page at SourceForge.")

(emacspeak-url-template-define
 "sourceforge browse mirrors"
 "http://prdownloads.sourceforge.net/%s/?sort_by=date"
 (list "Project name")
 nil
 "Retrieve download page  at Sourceforge for specified project.")

(emacspeak-url-template-define
 "sourceforge Download"
 "http://prdownloads.sourceforge.net/%s"
 (list "File: project/filename: ")
 nil
 "Download specified file."
 'browse-url
 'dont-url-encode)

;;}}}
;;{{{  MLB scores
;;; standings:

(emacspeak-url-template-define
 "MLB Scorecard"
                                        ;"http://gd.mlb.com/components/game/mlb/%s/master_scoreboard.xml"
 "http://gd.mlb.com/components/game/mlb/%s/scoreboard.xml"
 (list
  #'(lambda nil
      (let ((date
             (emacspeak-url-template-collect-date
              "Date: "
              "%Y-%m-%d"))
            (fields nil)
            (result nil))
        (setq fields (split-string date "-"))
        (setq result
              (format
               "year_%s/month_%s/day_%s"
               (first fields)
               (second fields)
               (third fields)))
        result))
  )
 'emacspeak-speak-buffer
 "Show MLB Scorecard."
 #'(lambda (url)
     (emacspeak-xslt-view-xml
      (expand-file-name "mlb-scorecard.xsl" emacspeak-xslt-directory)
      url)))

(emacspeak-url-template-define
 "Baseball standings"
 "http://www.mlb.com/NASApp/mlb/mlb/standings/index.jsp"
 nil
 nil
 "Display MLB standings."
 #'(lambda (url)
     (emacspeak-we-extract-table-by-match
      "Standings"
      url 'speak)))

(emacspeak-url-template-define
 "Baseball Game Index"
                                        ;"http://gd.mlb.com/components/game/%s"
 "http://gd.mlb.com/components/game/mlb/%s/"
 (list
  #'(lambda nil
      (let ((date
             (emacspeak-url-template-collect-date "Date: "
                                                  "%Y-%m-%d"))
            (fields nil)
            (result nil))
        (setq fields (split-string date "-"))
        (setq result
              (format
               "year_%s/month_%s/day_%s/"
               (first fields)
               (second fields)
               (third fields)))
        result)))
 nil
 "Display baseball Play By Play."
 )

(emacspeak-url-template-define
 "Baseball Play By Play"
 "http://gd.mlb.com/components/game/%s_%smlb_%smlb_1/playbyplay.html"
 (list
  #'(lambda nil
      (let ((date
             (emacspeak-url-template-collect-date
              "Date: "
              "%Y-%m-%d"))
            (fields nil)
            (result nil))
        (setq fields (split-string date "-"))
        (setq result
              (format
               "year_%s/month_%s/day_%s/gid_%s_%s_%s"
               (first fields)
               (second fields)
               (third fields)
               (first fields)
               (second fields)
               (third fields)))
        result))
  "Visiting Team: "
  "Home Team: ")
 nil
 "Display baseball Play By Play."
 )

(emacspeak-url-template-define
 "Baseball scores"
 "http://gd.mlb.com/components/game/mlb/%s_%smlb_%smlb_1/boxscore.html"
 (list
  #'(lambda nil
      (let ((date
             (emacspeak-url-template-collect-date
              "Date: "
              "%Y-%m-%d"))
            (fields nil)
            (result nil))
        (setq fields (split-string date "-"))
        (setq result
              (format
               "year_%s/month_%s/day_%s/gid_%s_%s_%s"
               (first fields)
               (second fields)
               (third fields)
               (first fields)
               (second fields)
               (third fields)))
        result))
  "Visiting Team: "
  "Home Team: ")
 nil
 "Display baseball scores."
 )

;;}}}
;;{{{ Listening to Air Traffic control

(emacspeak-url-template-define
 "Air Traffic Control"
 "http://www.liveatc.net/search?icao=%s"
 (list "Airport Code: ")
 nil
 "Find live streams for Air Traffic Control."
 #'(lambda (url)
     (emacspeak-we-extract-by-class
      "col1wrap"
      url
      'speak)))

;;}}}
;;{{{ flights from travelocity

(emacspeak-url-template-define
 "Travelocity Lookup"
 "http://dps1.travelocity.com/dparflifo.ctl?Service=TRAVELOCITY&GUEST=Y&last_pgd_page=ushpdeparr.pgd&aln_name=%s&flt_num=%s"
 (list
  "Airline:"
  "Flight Number:")
 nil
 "Show arrival/departure information from Travelocity."
 #'(lambda (url)
     (emacspeak-we-extract-table-by-match
      "Schedule" url 'speak)))

;;}}}
;;{{{  times of india

;;; create url rewrite url to get print page
(emacspeak-url-template-define
 "Times Of India"
 "http://www.timesofindia.com"
 nil
 #'(lambda ()
     (declare (special emacspeak-we-url-rewrite-rule))
     (setq emacspeak-we-url-rewrite-rule
           (list "$" "&prtPage=1")))
 "Retrieve Times Of India.
Set up URL rewrite rule to get print page."
 )

(emacspeak-url-template-define
 "Cartoon You Said It By Laxman"
 "http://www1.indiatimes.com/cartoon/%scart%s.htm"
 (list
  (lambda ()
    (read-from-minibuffer "Month: "
                          (downcase
                           (format-time-string "%h"))))
  (lambda ()
    (read-from-minibuffer "Date: "
                          (format-time-string "%d"))))
 'emacspeak-speak-buffer
 "Retrieve Cartoon Times Of India."
 )

;;}}}
;;{{{ meerkat
(defvar emacspeak-url-template-meerkat-profiles (make-hash-table
                                                 :test #'equal)
  "Map Meerkat profile names to profile codes.
Meerkat realy needs an xml-rpc method for getting this.")

(loop for e in
      (list
       '(1 "DEFAULT")
       '(10586 ".NET")
       '(1064 "Perl")
       '(1065 "Macintosh")
       '(13886 "WebServices.XML.com")
       '(1398 "O'ReillyNetForums")
       '(1665 "BSD")
       '(17 "Python")
       '(1746 "PHP")
       '(19 "Software")
       '(2281 "XML")
       '(27 "Web")
       '(4 "Apache")
       '(441 "Mozilla")
       '(4862 "P2P")
       '(4999 "O'Reilly")
       '(5 "Linux")
       '(563 "O'ReillyNetwork")
       '(6304 "XML.com")
       '(760 "Weblogs")
       '(9 "Wireless"))
      do
      (puthash (second e)  (first e)
               emacspeak-url-template-meerkat-profiles))

(defsubst emacspeak-url-template-meerkat-profile-names ()
  "Return alist of Meerkat profile names."
  (declare (special emacspeak-url-template-meerkat-profiles))
  (loop for k being the hash-keys of
        emacspeak-url-template-meerkat-profiles
        collect k))

(emacspeak-url-template-define
 "Meerkat Profile"
 "http://meerkat.oreillynet.com/?_fl=rss10&p=%s"
 (list
  #'(lambda nil
      (let((completion-ignore-case t)
           (profile
            (completing-read "Meerkat Profile:"
                             (emacspeak-url-template-meerkat-profile-names)
                             nil t)))
        (gethash profile emacspeak-url-template-meerkat-profiles))))
 nil
 "Meerkat Profile"
 #'(lambda (url)
     (emacspeak-webutils-rss-display url)))

(emacspeak-url-template-define
 "Meerkat Recipe"
 "http://meerkat.oreillynet.com/?_fl=rss10&%s"
 (list
  #'(lambda nil
      (read-from-minibuffer "Meerkat recipe: ")))
 nil
 "Meerkat tool"
 #'(lambda (url)
     (emacspeak-webutils-rss-display url)))

;;}}}
;;{{{  flight arrival

;;}}}
;;{{{ weather underground
;;;###autoload
(defcustom emacspeak-url-template-weather-city-state
  "95123"
  "Default city/state for weather forecasts"
  :type 'string
  :group 'emacspeak-url-template)

(emacspeak-url-template-define
 "rss weather from wunderground"
 "http://www.wunderground.com/auto/rss_full/%s.xml?units=both"
 (list
  #'(lambda nil
      (declare (special emacspeak-url-template-weather-city-state))
      (read-from-minibuffer "State/City:"
                            emacspeak-url-template-weather-city-state)))
 nil
 "Pull RSS weather feed for specified state/city."
 #'(lambda (url)
     (emacspeak-webutils-rss-display url)))

(emacspeak-url-template-define
 "Weather forecast from Weather Underground"
 "http://mobile.wunderground.com/cgi-bin/findweather/getForecast?query=%s"
 (list
  #'(lambda () (read-from-minibuffer "Zip: " emacspeak-url-template-weather-city-state)))
 'emacspeak-speak-buffer
 "Weather forecast from weather underground mobile."
 )

;;}}}
;;{{{ airport conditions:
(emacspeak-url-template-define
 "Airport conditions"
 "http://www.fly.faa.gov/flyfaa/flyfaaindex.jsp?ARPT=%s&p=0"
 (list "Airport Code:")
 nil
 "Display airport conditions from the FAA."
 #'(lambda (url)
     (emacspeak-we-extract-table-by-match "Status"
                                          url 'speak)))

;;}}}
;;{{{ emacs wiki search

(emacspeak-url-template-define
 "EmacsWiki Search"
 "http://www.emacswiki.org/cgi-bin/wiki?search=%s"
 (list "Search EmacsWiki For: ")
 #'(lambda nil
     (search-forward "Result page" nil t)
     (emacspeak-speak-line))
 "EmacsWiki Search")

;;}}}
;;{{{ reuters

(emacspeak-url-template-define
 "Reuters Finance"
 "http://today.reuters.com/stocks/Overview.aspx?ticker=%s&fs=1"
 (list "Ticker: ")
 nil
 "Reuters Finance Lookup")

;;}}}
;;{{{ ask

(emacspeak-url-template-define
 "ask search mobile"
 "http://mobile.ask.com/web.jsp?fi_what=%s&fi_Search=Search&form=web"
 (list "Ask Mobile Search: ")
 #'(lambda nil
     (search-forward "results")
     (emacspeak-speak-rest-of-buffer))
 "Mobile search using Ask.com")

(emacspeak-url-template-define
 "Ask Walking Directions"
 "http://mobile.ask.com/dd.jsp?fi_st_addr=%s&fi_end_addr=%s&fi_method=Walk&form=dd"
 (list "Start Address: "
       "End Address: ")
 #'(lambda()
     (search-forward "Time:")
     (beginning-of-line)
     (emacspeak-speak-rest-of-buffer))
 "Walking directions from Ask.com")

(emacspeak-url-template-define
 "Ask Local Search"
 "http://mobile.ask.com/local.jsp?fi_what=%s&fi_where=%s&fi_Search=Search&form=local)"
 (list "Find: "
       "Near: ")
 #'(lambda nil
     (search-forward "Sort")
     (forward-line 1)
     (emacspeak-speak-rest-of-buffer))
 "Ask Local Search.")
;;}}}
;;{{{  wordnet

(emacspeak-url-template-define
 "WordNet Search"
 "http://wordnet.princeton.edu/perl/webwn?s=%s"
 (list "WordNet Define: ")
 'emacspeak-speak-buffer
 "Look up term in WordNet.")

;;}}}
;;{{{ prairie home companion 

(emacspeak-url-template-define
 "PHC Prairie Home Companion"
 "http://www.publicradio.org/tools/media/player/phc/%s_phc.ram"
 (list 'emacspeak-url-template-date-year/month/date)
 nil
 "Play Prairie Home Companion"
 #'(lambda (url)
     (funcall emacspeak-media-player  url 'play-list))) 

(emacspeak-url-template-define
 "Earthquakes"
 "http://earthquake.usgs.gov/earthquakes/recenteqsus/Quakes/quakes_all.php"
 nil
 nil
 "Show table of recent quakes."
 #'(lambda (url)
     (emacspeak-we-xslt-filter "//tr[position() < 10]"
                               url
                               'speak)))

;;}}}
;;{{{  Radio station streams 

(emacspeak-url-template-define
 "StreamWorld Radio"
 "http://provisioning.streamtheworld.com/pls/%s.pls"
 (list
  #'(lambda () (upcase (read-from-minibuffer "Station ID: "))))
 nil
 "Play radio stream.
See http://www.cbsradio.com/streaming/index.html for a list of CBS  stations that use StreamTheWorld."
 #'(lambda (url)
     (emacspeak-m-player url 'playlist)))

;;}}}
;;}}}
;;{{{ Interactive commands

;;;###autoload
(defun emacspeak-url-template-open (ut)
  "Fetch resource identified by URL template."
  (declare (special  emacspeak-web-post-process-hook))
  (let ((fetcher (or (emacspeak-url-template-fetcher ut)
                     'browse-url))
        (url (emacspeak-url-template-url ut)))
    (when (and (emacspeak-url-template-post-action ut)
               (or (emacspeak-url-template-fetcher ut)
                   (emacspeak-webutils-supported-p)))
      (add-hook 'emacspeak-web-post-process-hook
                (emacspeak-url-template-post-action ut))
      (add-hook 'emacspeak-web-post-process-hook
                #'(lambda ()
                    (declare (special emacspeak-web-post-process-hook
                                      emacspeak-url-template-current-ut))
                    (rename-buffer
                     (downcase
                      (mapconcat #'identity
                                 (or
                                  emacspeak-url-template-current-ut
                                  (list "Untitled"))
                                 ": "))
                     'unique)
                    (setq emacspeak-web-post-process-hook nil))))
    (kill-new url)
    (funcall fetcher   url)))

(defsubst emacspeak-url-template-help-internal (name)
  "Display and speak help."
  (with-output-to-temp-buffer "*Help*"
    (princ name)
    (princ "\n\n")
    (princ
     (emacspeak-url-template-documentation
      (emacspeak-url-template-get name)))
    (save-excursion
      (set-buffer standard-output)
      (fill-region (point-min)
                   (point-max)))
    (help-print-return-message))
  (emacspeak-speak-help)
  (emacspeak-auditory-icon 'help))

(defvar emacspeak-url-template-current-ut nil
  "Records name and args of URL template we're executing.")

;;;###autoload
(defun emacspeak-url-template-fetch (&optional documentation)
  "Fetch a pre-defined resource.
Use Emacs completion to obtain a list of available resources.
Resources typically prompt for the relevant information
before completing the request.
Optional interactive prefix arg displays documentation for specified resource."
  (interactive "P")
  (declare (special emacspeak-url-template-current-ut
                    emacspeak-speak-messages))
  (let ((completion-ignore-case t)
        (emacspeak-speak-messages nil)
        (name  nil))
    (setq name
          (completing-read "Resource: "
                           emacspeak-url-template-table
                           nil
                           'must-match))
    (cond
     (documentation (emacspeak-url-template-help-internal name))
     (t
      (emacspeak-url-template-open
       (emacspeak-url-template-get name))))))

(defun emacspeak-url-template-help ()
  "Display documentation for  a URL template.
Use Emacs completion to obtain a list of available
resources."
  (interactive)
  (declare (special emacspeak-url-template-table))
  (let ((completion-ignore-case t)
        (name nil))
    (setq name
          (completing-read "Resource: "
                           emacspeak-url-template-table))
    (emacspeak-url-template-help-internal  name)))

;;}}}
;;{{{ Generate texinfo documentation for all defined url

(defun emacspeak-url-template-generate-texinfo-documentation (buffer)
  "Generates texinfo section documenting all defined URL
  templates."
  (declare (special emacspeak-url-template-table))
  (insert
   "@node URL Templates \n@section  URL Templates\n\n")
  (insert
   (format
    "This section is generated automatically from the source-level documentation.
Any errors or corrections should be made to the source-level
documentation.
This section documents a total of %d URL Templates.\n\n"
    (hash-table-count emacspeak-url-template-table)))
  (insert
   (format
    "All of these URL templates can be invoked via command
  @kbd{M-x emacspeak-url-template-fetch} normally bound to
  @kbd{%s}.
This command prompts for the name of the template, and completion
  is available via Emacs' minibuffer completion.
Each URL template carries out the following steps:
@itemize @bullet
@item Prompt for the relevant information.
@item Fetch the resulting URL using an appropriate fetcher.
@item Set up the resulting resource with appropriate
  customizations.
@end itemize

As an example, the URL templates that enable access to map directions
prompt for address and automatically
speak the relevant results.\n\n"
    (mapconcat #'key-description
               (where-is-internal
                'emacspeak-url-template-fetch)
               " ")))
  (let ((keys
         (sort
          (loop for key being the hash-keys of emacspeak-url-template-table
                collect key)
          'string-lessp)))
    (loop for key in keys
          do
          (insert
           (format "@kbd{%s}\n\n" key))
          (insert
           (emacspeak-url-template-documentation
            (emacspeak-url-template-get key)))
          (insert "\n\n"))))

;;}}}
(provide 'emacspeak-url-template)
;;{{{ end of file

;;; local variables:
;;; folded-file: t
;;; byte-compile-dynamic: nil
;;; end:

;;}}}
