I would like to write an Applescript that takes a RSS feed and returns the top 3 headlines. Basicly when I run it I would like my computer to just ‘read’ me (using Apple Speech) the top 3 headlines rom that particular feed. Is this a possible task, I would assume Applescript could do this however I dont know how to grab information over a network. Any help would be great! Thanks
When you say headline, do you mean the actual headline/title, or the whole article (headline and text)?
If you only want the headlines, then something like this should work:
property RSSURL : "http://scriptbuilders.net/scriptbuilders.xml"
try
do shell script "curl -sS " & quoted form of RSSURL & " | grep ' <title>' | head -n 3 | colrm 1 15 | cut -d \\< -f 1"
get paragraphs of result
repeat with thisLine in result
delay 2
say thisLine
end repeat
on error errorMsg number errorNum
display dialog "Error (" & errorNum & "):" & return & return & errorMsg buttons "Cancel" default button 1 with icon caution
end try
How can I change that so it only read the top 3, most recent, headlines from a given feed?
What feed are you trying to use?
I am using the top news headlines from CNN.
feed://rss.cnn.com/rss/cnn_topstories.rss
How can I extend it so it reads say the first paragraph or so of the article.
What I would like is a script that, when run, will greet me and say “These are the top news headlines for today”, reads me the top 3 headlines and articles and then tells me any items i have left on my ical to-do list.
What I have compiled so far looks like this:
property RSSURL : "feed://rss.cnn.com/rss/cnn_topstories.rss"
try
do shell script "curl -sS " & quoted form of RSSURL & " | grep ' <title>' | head -n 3 | colrm 1 15 | cut -d \\< -f 1"
get paragraphs of result
copy the (current date) to thedate
set theweekday to weekday of (current date)
set theday to day of (current date)
set themonth to month of (current date)
set theyear to year of (current date)
set todaydate to theweekday & themonth & theday & theyear
set thetime to time of (current date)
if thetime < 43200 then
set thegreeting to "Good Morning"
else if thetime < 64800 then
set thegreeting to "Good Afternoon"
else
set thegreeting to "Good Evening"
say thegreeting & "This is the current report for. " & todaydate & "The Current time is" & thetime
delay 2
say "Today's top news headlines are"
repeat with thisLine in result
delay 2
say thisLine
end repeat
set theCalendar to "TODO" -- change to your calendar name
set myList to {}
tell application "iCal"
set {myComps, mySumms} to {completion date, summary} of todos of calendar theCalendar
repeat with myItem from 1 to count of myComps
if (item myItem of myComps) contains missing value then set the end of myList to (item myItem of mySumms)
end repeat
end tell
say myList
In parts this works, but I would like to get the entire feed description and have the TODO items spoken in order. I cant figure out how to to that.
I appriciate this, I am new to Applescript, but am finding it a great and explorable proramming language for everything!
Real chore to do it with AppleScript unless you’re using a scriptable RSS reader application as there’s no good RSS libraries for AS. Easy if you use Python and the excellent Universal Feed Parser module:
#!/usr/bin/env python
import os, time
import feedparser
d = feedparser.parse('http://rss.cnn.com/rss/cnn_topstories.rss')
def say(s):
os.system("say '%s'" % s.replace("'", "''\\'''"))
for entry in d.entries[0:3]:
say(entry.title)
say(entry.summary)
time.sleep(1)
HTH
Try something like this:
property RSSURL : "http://rss.cnn.com/rss/cnn_topstories.rss"
set ASTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to {("<item>" & (ASCII character 13))}
try
do shell script "curl -sS " & quoted form of RSSURL
set rssFeed to every text item of result
set AppleScript's text item delimiters to ASTID
if (count rssFeed) is greater than or equal to 4 then
set rssFeed to items 2 thru 4 of rssFeed
else
set rssFeed to items 2 thru (count rssFeed) of rssFeed
end if
on error errorMsg number errorNum
set AppleScript's text item delimiters to ASTID
display dialog "Error (" & errorNum & "):" & return & return & errorMsg buttons "Cancel" default button 1 with icon caution
end try
say "These are the top news headlines for today."
delay 2
repeat with thisPiece in rssFeed
say (text 8 thru -9 of (first paragraph of thisPiece))
delay 1
say (text 14 thru -15 of (third paragraph of thisPiece))
delay 2
end repeat
say "End of headlines."
Unfortunately, items inside RSS feeds are not always sorted by publication date. I’m not sure how to handle that.
If you want to see the results of this script, replace the end of the script with something like this:
set newsList to {}
repeat with thisPiece in rssFeed
set newsList's end to (text 8 thru -9 of (first paragraph of thisPiece))
set newsList's end to (text 14 thru -15 of (third paragraph of thisPiece))
end repeat
return newsList
set newsList to {}
repeat with thisPiece in rssFeed
set newsList's end to {title:(text 8 thru -9 of (first paragraph of thisPiece)), summmary:(text 14 thru -15 of (third paragraph of thisPiece))}
end repeat
return newsList
Note that this code assumes each RSS item contains a title, link, and description element (in that order).
Note that AS’s built-in text handling facilities and tools like grep are seriously inadequate for processing XML. If you must use AppleScript for XML work (other languages are much better), at least use something like System Events’ XML Suite (10.4+) or XMLLib.osax.
Using System Events’ XML Suite:
property RSSURL : "http://rss.cnn.com/rss/cnn_topstories.rss"
property RSSFile : POSIX path of ((path to temporary items as Unicode text) & "rss.xml")
tell application "System Events"
activate
try
do shell script "curl -sS " & quoted form of RSSURL & " > " & quoted form of RSSFile
set rssFeed to XML file RSSFile
set rssItems to XML elements 1 thru 3 of XML element "channel" of XML element "rss" of contents of rssFeed whose name is "item"
get value of XML element "title" of XML element "channel" of XML element "rss" of contents of rssFeed
say "These are today's top news headlines from " & result
delay 2
on error errorMsg number errorNum
display alert "Error " & errorNum message errorMsg buttons "Cancel" default button 1
return false
end try
repeat with thisItem in rssItems
try
say (get value of XML element "title" of thisItem)
on error
say "No title for this item."
end try
delay 1
try
say (get value of XML element "description" of thisItem)
on error
say "No description for this item."
end try
delay 2
end repeat
say "End of headlines."
end tell
I’m still not sure how to sort by date.
Google for “Schwartzian transform”. Example using AppleMods’ List library:
property _Loader : run application "LoaderServer"
----------------------------------------------------------------------
-- DEPENDENCIES
property _List : missing value
on __load__(loader)
set _List to loader's loadLib("List")
end __load__
----------------------------------------------------------------------
__load__(_Loader's makeLoader())
tell application "Finder"
tell every item of home
set itemDates to its modification date
set itemRefs to it
end tell
end tell
set lst to _List's recomposeList({itemDates, itemRefs})
set lst to _List's sortListOfLists(lst, {1})
set sortedItemRefs to _List's recomposeList(lst)'s item 2
(Feel free to add the above to Code Exchange if you like; it seems to be a fairly regular question.)
Interesting.